最佳算法以避免嵌套循环而不采用蛮力方法

huangapple go评论171阅读模式
英文:

Best Algorithm to avoid nested loops without Brute Force approach

问题

I want to make this method run as fast as possible.

int[] p = new int[] {1,4,4,5,1,3,6};
int[] q = new int[] {2,1,3,1,6,4,3};
int k =4.
void nestLoop(){
for(int i = 0; i < q.length; i++){
for(int j = 0; j < p.length; j++){
//code continues
// inside here...
//This approach
// takes a longer
//time to finish
// executing. I need a better algorithm

  }

}
}

To be clearer; at q[0], p = 1, since 1 is less than q[0], choose 1, and p[4] is also lower, choose 1; hence the answer when it is q[0] are 1 and 1 : but because 1 and 1 are two ints, they are not equal to k = 4, then return 0. If the answer had been 1, 1,1,1 then the number is 4 which is equal to k. [1,1,1,1] will be returned. The same for other q and so on

英文:

I want to make this method run as fast as possible.

int[] p = new int[] {1,4,4,5,1,3,6};
int[] q = new int[] {2,1,3,1,6,4,3};
int k =4.
void nestLoop(){
 for(int i = 0; i &lt; q.length; i++){
     for(int j = 0; j &lt; p.length; j++){
       //code continues 
       // inside here...
       //This approach 
        // takes a longer 
         //time to finish 
         // executing. I need a better algorithm

      }


  }
}

To be clearer; at q[0], p = 1, since 1 is less than q[0], choose 1, and p[4] is also lower, choose 1; hence the answer when it is q[0] are 1 and 1 : but because 1 and 1 are two ints, they are not equal to k = 4, then return 0. If the answer had been 1, 1,1,1 then the number is 4 which is equal to k. [1,1,1,1] will be returned. The same for other q and so on

答案1

得分: 2

如果我理解正确,您要返回的要么是 k 或 0,对吗?

然后这是实现方式:

int[] p = new int[] {1,4,4,5,1,3,6};
int[] q = new int[] {2,1,3,1,6,4,3};
int k = 4;

void notNested()
{
    TreeSet<Integer> ts = new TreeSet<Integer>();
    // 在数组中找到第 k 小的数字。
    PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder());
    for (int p1 : p)
    {
        if (pq.size() < k)
        {
            pq.add(p1);
        } else if (pq.peek() > p1)
        {
            pq.poll();
            pq.add(p1);
        }
    }

    int ksm = pq.poll();
    // 对于每个 q,只与第 k 小的数字比较。
    for (int q1 : q)
    {
        if (q1 >= ksm)
        {
            results.add(k);
        }
        else
        {
            results.add(0);
        }
    }
}

请注意,代码中有一个错误,int k =4. 应该改为 int k = 4;,修正了这个错误后,代码应该正常运行。

英文:

If I understand correctly you are returning either k or 0, correct?

Then this is the way to do it:

int[] p = new int[] {1,4,4,5,1,3,6};
int[] q = new int[] {2,1,3,1,6,4,3};
int k =4.

void notNested()
{
    TreeSet&lt;Integer&gt; ts = new TreeSet&lt;Integer&gt;();
    // Find the kth smallest number in the array.
    PriorityQueue&lt;Integer&gt; pq = new PriorityQueue&lt;&gt;(Comparator.reverseOrder());
    for (int p1 : p)
    {
        if (pq.size() &lt; k)
        {
            pq.add(p1);
        } else if (pq.peek() &gt; p1)
        {
            pq.poll();
            pq.add(p1);
        }
    }

    int ksm = pq.poll();
    // For each q, compare against kth smallest only.
    for (int q1 : q)
    {
        if (q1 &gt;= ksm)
        {
            results.add(k);
        }
        else
        {
            results.add(0);
        }
    }
}

答案2

得分: 1

如果p中的不同元素数量相对较小,与总元素数量相比,以下方法可能有效。然而,如果有许多不同元素,甚至所有元素都不同,那么它将变得更慢。

  • 创建一个将元素映射到它们的索引的Map,例如[1,4,4,5,1,3,6]将变为{1: [0,4], 4: [1,2], 5: [3], 3: [5], 6: [6]}
  • 从该映射中,获取所有小于q中当前元素的元素的索引列表
  • 将它们放入一个堆或优先队列中,按照该元素的下一个未使用的索引进行排序
  • 从堆中弹出列表,获取第一个索引,并将它们放回堆中以获取下一个索引,直到获得k个索引

如果有许多重复的元素(仅在这种情况下),这可能会略微降低复杂度。对于p中的P个元素,其中有d个不同元素,在q中有Q个元素,并且有k个操作,这应该具有复杂度O(P + Q*(d+k*log(d)))P用于创建映射,d用于选择列表和k堆操作,log(d)用于所有Q个查询)。

英文:

If the number of different elements in p is relatively small compared to the total number of elements, the following might work. If, however, there are many different elements, or even all elements are different, then it will be much slower.

  • create a Map mapping elements to their indices, e.g. [1,4,4,5,1,3,6] would become {1: [0,4], 4: [1,2], 5: [3], 3: [5], 6: [6]}
  • from that map, get the lists of indices for all elements smaller than the current element from q
  • put those into a Heap, or Priority Queue, sorted by the next unused index for that element
  • pop lists from the heap, get the first index, and put them back onto the heap for the next index until you get k indices

If there are many repeated elements (and only then), this may somewhat reduce the complexity. For P elements in p, d of which being distinct, Q elements in q, and k, this should have complexity of O(P + Q*(d+k*log(d))) (P for creating the map, and d for selecting the lists and k heap operation with log(d) for all the Q queries).

答案3

得分: 1

这是一个使用Java Streams的解决方案:

package javaapplication3;
import java.util.Arrays;
import java.util.stream.*;

public class JavaApplication3 {
    public static void main(String[] args) {

        int[] p = new int[] {1,4,4,5,1,3,6};
        int[] q = new int[] {2,1,3,1,6,4,3};
        int[][] results = new int[q.length][]; // 用于存储结果的数组
        int k = 4;

        // 对于每个元素 q[i],并行执行
        IntStream.range(0, q.length).parallel().forEach(i -> {
            final int qi = q[i];
            // 获取 p 中不大于 q[i] 的前 k 个元素
            results[i] = Arrays.stream(p).filter(v -> v <= qi).limit(k).toArray();
        });

        for(int i=0; i<q.length; i++) {
            int[] result = results[i];
            System.out.print("Values less or equal than " + q[i] + ": {");
            for (int v : result)
                System.out.print(" " + v);
            System.out.println(" }");
        }

    }    
}

输出:

Values less or equal than 2: { 1 1 }
Values less or equal than 1: { 1 1 }
Values less or equal than 3: { 1 1 3 }
Values less or equal than 1: { 1 1 }
Values less or equal than 6: { 1 4 4 5 }
Values less or equal than 4: { 1 4 4 1 }
Values less or equal than 3: { 1 1 3 }

注意:你可以选择对 p 进行排序,这会在 p 很大且 k 很小时提高性能。

英文:

This is a solution using Java Streams:

package javaapplication3;
import java.util.Arrays;
import java.util.stream.*;

public class JavaApplication3 {
    public static void main(String[] args) {

        int[] p = new int[] {1,4,4,5,1,3,6};
        int[] q = new int[] {2,1,3,1,6,4,3};
        int[][] results = new int[q.length][]; // Array of arrays to store results
        int k =4;
        
        // For each element q[i], execute in parallel
        IntStream.range(0, q.length).parallel().forEach(i -&gt; {
            final int qi = q[i];
            // Get first k elements of p &lt;= q[i]
            results[i] = Arrays.stream(p).filter(v -&gt; v &lt;= qi).limit(k).toArray();            
        });
        
        for(int i=0; i&lt;q.length; i++) {
            int[] result = results[i];
            System.out.print(&quot;Values less or equal than &quot; + q[i] + &quot;: {&quot;);
            for (int v : result)
                System.out.print(&quot; &quot; + v);
            System.out.println(&quot; }&quot;);
        }

    }    
}

Output:

Values less or equal than 2: { 1 1 }
Values less or equal than 1: { 1 1 }
Values less or equal than 3: { 1 1 3 }
Values less or equal than 1: { 1 1 }
Values less or equal than 6: { 1 4 4 5 }
Values less or equal than 4: { 1 4 4 1 }
Values less or equal than 3: { 1 1 3 }

Note: You can optionally sort p which will improve performance if p is large and k is small.

huangapple
  • 本文由 发表于 2020年8月5日 23:01:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/63267976.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定