// Checks whether the array contains two elements whose sum is s.
// Input: A list of numbers and an integer s
// Output: return True if the answer is yes, else return False
public static boolean calvalue (int[] numbers, int s){
for (int i=0; i< numbers.length; i++){
for (int j=i+1; j<numbers.length;j++){
if (numbers[i] < s){
if (numbers[i]+numbers[j] == s){
return true;
}
}
}
}
return false;
}
答案 0 :(得分:12)
这可以在O(n)中实现。
n
,计算s-n = d
,然后检查集合中是否存在d
。如果存在d
,则n+d = s
,则返回true
。如果您在未找到合适的d
的情况下通过列表,请返回false
。这是通过列表的单次传递实现的,每次查找都采用O(1),因此这一步也需要O(n)。答案 1 :(得分:7)
这篇文章的其他答案中提到的解决方案以及其他一些答案(例如使用位图而不是散列表)都出现在以下重复内容和问题的略微变化中:
•Find two elements in an array that sum to k,
•Find a pair of elements from an array whose sum equals a given number,
•Determine whether or not there exist two elements in set s whose sum is exactly,
•Checking if 2 numbers of array add up to i,
•Find pair of numbers in array that add to given sum,
•Design an algorithm to find all pairs of integers within an array which sum to a,
•Given an unsorted array find any two elements in the array whose sum is equal t,
•A recursive algorithm to find two integers in an array that sums to a given inte,
•Find 2 numbers in an unsorted array equal to a given sum,
•Find two elements so sum is equal to given value,
•并且,根据Google,many more。
答案 2 :(得分:5)
你可以通过对数组进行排序来解决这个问题,然后保持2个指针指向数组的开始和结束,并通过移动两个指针找到2个数字。排序步骤采用O(nlog n),第二步采用O(n)。
正如@Adam指出的那样,从阵列中删除重复的元素也是一件好事,这样如果数组中包含许多重复的数字,你可以减少第二步的时间。
关于如何进行第二步:
为什么这是正确的(我使用右端表示较大的末端,左端表示较小的末端):
答案 3 :(得分:1)
这是一个考虑重复条目的解决方案。它是用javascript编写的,并假设数组已排序。
var count_pairs = function(_arr,x) {
if(!x) x = 0;
var pairs = 0;
var i = 0;
var k = _arr.length-1;
if((k+1)<2) return pairs;
var halfX = x/2;
while(i<k) {
var curK = _arr[k];
var curI = _arr[i];
var pairsThisLoop = 0;
if(curK+curI==x) {
// if midpoint and equal find combinations
if(curK==curI) {
var comb = 1;
while(--k>=i) pairs+=(comb++);
break;
}
// count pair and k duplicates
pairsThisLoop++;
while(_arr[--k]==curK) pairsThisLoop++;
// add k side pairs to running total for every i side pair found
pairs+=pairsThisLoop;
while(_arr[++i]==curI) pairs+=pairsThisLoop;
} else {
// if we are at a mid point
if(curK==curI) break;
var distK = Math.abs(halfX-curK);
var distI = Math.abs(halfX-curI);
if(distI > distK) while(_arr[++i]==curI);
else while(_arr[--k]==curK);
}
}
return pairs;
}
享受!
答案 4 :(得分:0)
在Java中
private static boolean find(int[] nums, long k, int[] ids) {
// walk from both sides towards center.
// index[0] keep left side index, index[1] keep right side index,
// runtime O(N)
int l = ids[0];
int r = ids[1];
if (l == r) {
ids[0] = -1;
ids[1] = -1;
return false;
}
if (nums[l] + nums[r] == k) {
ids[0]++;
ids[1]++;
return true;
}
if (nums[l] + nums[r] < k) {
ids[0]++;
} else {
ids[1]--;
}
return find(nums, k, ids);
}
public static boolean twoSum(final int[] nums, int target) {
// Arrays.sort(nums); //if the nums is not sorted, then sorted it firstly, thus the running time will be O(NlogN)
int[] ids = new int[2];
ids[0] = 0;
ids[1] = nums.length - 1;
return find(nums, target, ids);
}
测试
@Test(timeout = 10L, expected = Test.None.class)
public void test() {
Assert.assertEquals( twoSum(new int[]{3, 2, 4}, 6), true);
Assert.assertEquals( twoSum(new int[]{3, 2, 4}, 8), false);
}
如果只有答案是不够的,并想知道哪一个是i和j,那么A [i] + A [j] =目标
以@cheeken的想法如下,如果有重复的数字,首先出现一个。
public static int[] twoSum2(final int[] nums, int target) {
int[] r = new int[2];
r[0] = -1;
r[1] = -1;
Set<Integer> set = new HashSet<>(nums.length);
Map<Integer, List<Integer>> map = new HashMap<>(nums.length);
for (int i = 0; i < nums.length; i++) {
int v = nums[i];
if (set.contains(target - v)) {
r[0] = map.get(target - v).get(0);
r[1] = i;
return r;
}
set.add(v);
List ids = map.get(v);
if (ids == null) {
ids = new LinkedList<>();
ids.add(i);
map.put(v, ids);
} else {
ids.add(i);
map.put(v, ids);
}
}
return r;
}
测试
int[] r = twoSum2(new int[]{3, 2, 4}, 6);
Assert.assertEquals(r[0], 1);
Assert.assertEquals(r[1], 2);
r = twoSum2(new int[]{3, 2, 4}, 8);
Assert.assertEquals(r[0], r[1]);
Assert.assertEquals(r[1], -1);