下面是我的代码,用于获取数组的索引,其值的和对应于给定的目标值。目前最坏的情况是O(N2)算法。有什么改进的方法吗?
public class SumArrayTarget {
public static void main(String[] args) {
int[] arr = { 1, 2, 4, 6, 3, 5, 7 };
System.out.println("The indices are "+ Arrays.toString(sum(arr, 12)));
}
public static int[] sum(int[] arr, int target) {
int[] list = new int[2];
for (int i = 0; i < arr.length - 1; i++) {
int j = i+1;
while (j < arr.length) {
if (arr[i] + arr[j++] == target){
list[0]=i;
list[1]=j-1;
return list;
}
}
}
return list;
}
}
>
是的,我将从排序数组开始。
但在那之后,我将只使用二叉树来查找第一个(现在是当前)元素的对。
即使当前元素没有正确的对,我也会记得我寻找它的地方。
对于下一个元素,我将从记忆中的位置向后寻找对。
返回到2,直到被查找对的索引满足。
对于一个非常大的数组arr
,可以通过对数组进行排序(即O(N logn)),使其成为O(N logn),然后对每个元素arr[i]
,对数组的其余部分arr[i 1]
进行二进制搜索(不是最好的,请参见下文),直到最后一个查找target-arr[i]
的元素。二进制搜索是O(logn),所以整个算法是O(nlogn)。这需要一个相当大的N才能使它有价值——比7大得多。
您可以在当前代码中节省一点时间:(1)如果在开始内部循环之前计算x=target-arr[i]
,并在内部循环中选中arr[j]==x
。(2) 如果你知道问题的一个条件是arr
的所有元素都是正的,那么在你像上面那样计算x
之后,如果x,你可以完全跳过内部循环
附言:如果找不到结果,请确保您知道要返回什么。您当前的代码将返回一个2元素数组,其中两个元素都是0。这可能没关系,因为调用者可以检查这一点,但是最好返回
null
,特别是因为0是在其中一个元素中返回的有效值。
PPS。再考虑一下,一旦你对数组进行了排序,你就不需要进行二进制搜索来得到答案;你应该能够在O(N)时间内完成,让一个索引在数组中前进,另一个索引在数组中后退。此外,当你排序时,你可能想要创建一些小对象,其中包括
arr
中的值和原始索引,并对它们进行排序,这样你就可以把原始索引放在返回数组中。或者只需搜索arr
中找到的两个值,即O(N)。
您的算法假设总有两个数字相加到所需的目标。如果没有,则返回索引{0,0}的空列表。如果这是您需要的行为,那么我可以想到一个复杂度的改进:
这使得算法的总运行时间达到预期的O(n),但是开销很大。对于小于一百万的输入数组,您的蛮力方法可能更好。
如果你试图回答的问题也允许两个以上的索引,那么你就有了整数背包问题。你可以在谷歌上搜索,但它会变得更加复杂!
编辑:添加示例实现。
public static int[] sum(int[] arr,int target) {
LinkedHashMap<Integer,Integer> map = new LinkedHashMap<Integer>(arr.length);
for(i = 0;i < arr.length;i++) {
map.add(arr[i],i);
}
for(Map.Entry<Integer,Integer> entry : map.entrySet()) {
int n = entry.getValue();
int index = entry.getKey();
if(map.containsKey(target - n)) {
return new int[] {index,map.get(target - n)};
}
}
return null;
}
问题内容: 我想计算所有奇数数组索引的总和,但是在寻找正确的方法时遇到了一些麻烦。 到目前为止,这是我的代码: 关于为何不起作用的任何想法,或者更简单的方法?为了澄清,我想在奇数数组索引位置添加所有数字,所以。 编辑: 忘记提及我只想添加1、3、5、7、9、11,而不是13。 问题答案: 刚刚编辑了代码:
问题内容: 有没有更好的方法来实现这一目标? 注意: Arrays.asList(a)返回由指定数组支持的固定大小的列表。 (将返回的列表更改为“直写”到数组。)。我不要那种行为 我认为我上面的功能绕过了(或者我错了吗?) 因此,这里有另一种方法: 只看它, 我相信它比第一种方法更快 。 问题答案: 您用更好的方式表示什么: 更具可读性: 更少的内存消耗,并且可能更快(但绝对不是线程安全的): 顺
有没有一种简单的方法可以在访问流中的索引的同时对流进行迭代? 这与上面给出的LINQ示例相比似乎相当令人失望 有没有更简洁的方式? 而且,拉链似乎不是动了就是被拆了...
我使用Utinyripper将游戏解码为unity项目,将其移植到pc上,但unity中有一个编译错误。我知道c#非常糟糕,所以如果你能帮忙,请帮帮我。 错误:
我有一个数字数组,现在我必须通过生成给定数组的所有可能子数组并应用一些条件来找到元素之和。 条件是,对于每个子阵列,获取最小值,并找到其中的元素总数,然后将两者相乘(最小值*总数)。最后,将所有子阵列的所有这些相乘值相加。 以下是问题陈述: 使用下面的公式找到所有可能的子数组的总和: 和(左,右)=(最小的arr[i]) * (∑ arr[i]),其中i的范围从左到右。 例子: 子数组是:[sta
问题内容: 我只是在玩JavaScript而被一个简单的程序所困扰。 我在JavaScript中声明了一个数组 然后,由于JavaScript中没有固定的数组大小,我们可以向数组中添加更多的大小,因此我向数组中添加了另一个整数。 和预期的一样,如果我尝试访问,我肯定会获得。 现在,如果我取一个数组 并添加另一个元素 我故意没有定义,而这也给了我作为。 这是一个可以观察到的小提琴:http : //