我们需要在数组中找到一对数,其总和等于给定值。
A = {6,4,5,7,9,1,2}
总和= 10 然后这些对是 - {6,4},{9,1}
我有两个解决方案。
sum-hash[i]
。但问题是,虽然第二种解决方案是O(n)时间,但也使用O(n)空间。
所以,我想知道我们是否可以在 O(n)时间和 O(1)空间中进行。这不是功课!
答案 0 :(得分:18)
使用就地基数排序和OP的第一个带有2个迭代器的解决方案,相互接近。
如果数组中的数字不是某种多精度数字并且例如是32位整数,则可以使用几乎没有额外空间(每次传递1位)在2 * 32次传递中对它们进行排序。或者2 * 8遍和16个整数计数器(每遍4位)。
2个迭代器解决方案的详细信息:
第一个迭代器最初指向排序数组的第一个元素并向前推进。第二个迭代器最初指向数组的最后一个元素并向后前进。
如果迭代器引用的元素总和小于所需的值,则前进第一个迭代器。如果它大于所需的值,则前进第二个迭代器。如果它等于所需的值,则成功。
只需要一次通过,因此时间复杂度为O(n)。空间复杂度为O(1)。如果使用基数排序,整个算法的复杂性是相同的。
如果您对相关问题感兴趣(总和超过2个数字),请参阅"Sum-subset with a fixed subset size"和"Finding three elements in an array whose sum is closest to an given number"。
答案 1 :(得分:6)
这是来自微软亚洲研究院的经典访谈问题
如何在未排序的数组中找到等于给定总和的2个数字。
[1]蛮力解决方案
这个算法很简单。时间复杂度为O(N ^ 2)
[2]使用二进制搜索
使用bianry搜索找到每个arr [i]的Sum-arr [i],时间复杂度可以减少到O(N * logN)
[3]使用Hash
基于[2]算法并使用哈希,时间复杂度可以减少到O(N),但是这个解决方案将添加哈希的O(N)空间。
[4]最优算法:
Pseduo代码:
for(i=0;j=n-1;i<j)
if(arr[i]+arr[j]==sum) return (i,j);
else if(arr[i]+arr[j]<sum) i++;
else j--;
return(-1,-1);
或
If a[M] + a[m] > I then M--
If a[M] + a[m] < I then m++
If a[M] + a[m] == I you have found it
If m > M, no such numbers exist.
而且,这个问题完全解决了吗?否。如果数字是N.这个问题将变得非常复杂。
问题然后:
如何找到具有给定数字的所有组合案例?
这是一个经典的NP-Complete问题,称为subset-sum。
要了解NP / NPC / NP-Hard,您最好阅读一些专业书籍。
参考文献:
[1] http://www.quora.com/Mathematics/How-can-I-find-all-the-combination-cases-with-a-given-number
[2] http://en.wikipedia.org/wiki/Subset_sum_problem
答案 2 :(得分:3)
for (int i=0; i < array.size(); i++){
int value = array[i];
int diff = sum - value;
if (! hashSet.contains(diffvalue)){
hashSet.put(value,value);
} else{
printf(sum = diffvalue + hashSet.get(diffvalue));
}
}
--------
Sum being sum of 2 numbers.
答案 3 :(得分:1)
如果您假设对的总和值M
是常量并且数组中的条目是正数,那么您可以在一次传递中执行此操作(O(n)
时间)使用M/2
指针(O(1)
空格)如下所示。指针标记为P1,P2,...,Pk
,其中k=floor(M/2)
。然后做这样的事情
for (int i=0; i<N; ++i) {
int j = array[i];
if (j < M/2) {
if (Pj == 0)
Pj = -(i+1); // found smaller unpaired
else if (Pj > 0)
print(Pj-1,i); // found a pair
Pj = 0;
} else
if (Pj == 0)
Pj = (i+1); // found larger unpaired
else if (Pj < 0)
print(Pj-1,i); // found a pair
Pj = 0;
}
}
例如,您可以通过将索引存储为基数N
中的数字来处理重复的条目(例如,两个6)。对于M/2
,您可以添加条件
if (j == M/2) {
if (Pj == 0)
Pj = i+1; // found unpaired middle
else
print(Pj-1,i); // found a pair
Pj = 0;
}
但是现在你有把这些配对放在一起的问题。
答案 4 :(得分:1)
<html>
<head>
<title>What you want to name the webpage</title>
</head>
</html>
答案 5 :(得分:0)
创建一个包含Key的字典(列表中的数字),Value是获取所需值所需的数字。接下来,检查列表中是否存在数字对。
def check_sum_in_list(p_list, p_check_sum):
l_dict = {i: (p_check_sum - i) for i in p_list}
for key, value in l_dict.items():
if key in p_list and value in p_list:
return True
return False
if __name__ == '__main__':
l1 = [1, 3, 7, 12, 72, 2, 8]
l2 = [1, 2, 2, 4, 7, 4, 13, 32]
print(check_sum_in_list(l1, 10))
print(check_sum_in_list(l2, 99))
Output:
True
Flase
第2版
import random
def check_sum_in_list(p_list, p_searched_sum):
print(list(p_list))
l_dict = {i: p_searched_sum - i for i in set(p_list)}
for key, value in l_dict.items():
if key in p_list and value in p_list:
if p_list.index(key) != p_list.index(value):
print(key, value)
return True
return False
if __name__ == '__main__':
l1 = []
for i in range(1, 2000000):
l1.append(random.randrange(1, 1000))
j = 0
i = 9
while i < len(l1):
if check_sum_in_list(l1[j:i], 100):
print('Found')
break
else:
print('Continue searching')
j = i
i = i + 10
Output:
...
[154, 596, 758, 924, 797, 379, 731, 278, 992, 167]
Continue searching
[808, 730, 216, 15, 261, 149, 65, 386, 670, 770]
Continue searching
[961, 632, 39, 888, 61, 18, 166, 167, 474, 108]
39 61
Finded
[Finished in 3.9s]
答案 6 :(得分:0)
显而易见的解决方案是否无效(迭代每对连续)或两个数字是否为任何顺序?
在这种情况下,您可以对数字列表进行排序,并使用随机抽样对已排序的列表进行分区,直到您有一个足够小的子列表进行迭代。
答案 7 :(得分:0)
//使用哈希的Java实现 import java.io。*;
类PairSum { private static final int MAX = 100000; // Hashmap的最大大小
static void printpairs(int arr[],int sum)
{
// Declares and initializes the whole array as false
boolean[] binmap = new boolean[MAX];
for (int i=0; i<arr.length; ++i)
{
int temp = sum-arr[i];
// checking for condition
if (temp>=0 && binmap[temp])
{
System.out.println("Pair with given sum " +
sum + " is (" + arr[i] +
", "+temp+")");
}
binmap[arr[i]] = true;
}
}
// Main to test the above function
public static void main (String[] args)
{
int A[] = {1, 4, 45, 6, 10, 8};
int n = 16;
printpairs(A, n);
}
}
答案 8 :(得分:0)
如果数字不是很大,你可以使用快速傅里叶变换乘以两个多项式,然后在O(1)中检查x ^(所需总和)和之前的系数是否大于零。 O(n log n)总计!
答案 9 :(得分:0)
https://github.com/clockzhong/findSumPairNumber
#! /usr/bin/env python
import sys
import os
import re
#get the number list
numberListStr=raw_input("Please input your number list (seperated by spaces)...\n")
numberList=[int(i) for i in numberListStr.split()]
print 'you have input the following number list:'
print numberList
#get the sum target value
sumTargetStr=raw_input("Please input your target number:\n")
sumTarget=int(sumTargetStr)
print 'your target is: '
print sumTarget
def generatePairsWith2IndexLists(list1, list2):
result=[]
for item1 in list1:
for item2 in list2:
#result.append([item1, item2])
result.append([item1+1, item2+1])
#print result
return result
def generatePairsWithOneIndexLists(list1):
result=[]
index = 0
while index< (len(list1)-1):
index2=index+1
while index2 < len(list1):
#result.append([list1[index],list1[index2]])
result.append([list1[index]+1,list1[index2]+1])
index2+=1
index+=1
return result
def getPairs(numList, target):
pairList=[]
candidateSlots=[] ##we have (target-1) slots
#init the candidateSlots list
index=0
while index < target+1:
candidateSlots.append(None)
index+=1
#generate the candidateSlots, contribute O(n) complexity
index=0
while index<len(numList):
if numList[index]<=target and numList[index]>=0:
#print 'index:',index
#print 'numList[index]:',numList[index]
#print 'len(candidateSlots):',len(candidateSlots)
if candidateSlots[numList[index]]==None:
candidateSlots[numList[index]]=[index]
else:
candidateSlots[numList[index]].append(index)
index+=1
#print candidateSlots
#generate the pairs list based on the candidateSlots[] we just created
#contribute O(target) complexity
index=0
while index<=(target/2):
if candidateSlots[index]!=None and candidateSlots[target-index]!=None:
if index!=(target-index):
newPairList=generatePairsWith2IndexLists(candidateSlots[index], candidateSlots[target-index])
else:
newPairList=generatePairsWithOneIndexLists(candidateSlots[index])
pairList+=newPairList
index+=1
return pairList
print getPairs(numberList, sumTarget)
我在O(n + m)时间和空间成本下成功实现了一个Python解决方案。 “m”表示这两个数和的总和所需的目标值。 我相信这是最低的成本。 Erict2k使用了itertools.combinations,与我的算法相比,它也会花费相似或更高的时间和空间成本。
答案 10 :(得分:0)
import itertools
list = [1, 1, 2, 3, 4, 5,]
uniquelist = set(list)
targetsum = 5
for n in itertools.combinations(uniquelist, 2):
if n[0] + n[1] == targetsum:
print str(n[0]) + " + " + str(n[1])
1 + 4
2 + 3
答案 11 :(得分:0)
如果数组中的两个整数与比较整数匹配,则以下代码返回true。
function compareArraySums(array, compare){
var candidates = [];
function compareAdditions(element, index, array){
if(element <= y){
candidates.push(element);
}
}
array.forEach(compareAdditions);
for(var i = 0; i < candidates.length; i++){
for(var j = 0; j < candidates.length; j++){
if (i + j === y){
return true;
}
}
}
}
答案 12 :(得分:0)
如果它是一个排序数组,我们只需要一对数字而不是所有对,我们就可以这样做:
public void sums(int a[] , int x){ // A = 1,2,3,9,11,20 x=11
int i=0 , j=a.length-1;
while(i < j){
if(a[i] + a[j] == x) system.out.println("the numbers : "a[x] + " " + a[y]);
else if(a[i] + a[j] < x) i++;
else j--;
}
}
1 2 3 9 11 20 || i = 0,j = 5 sum = 21 x = 11
1 2 3 9 11 20 || i = 0,j = 4 sum = 13 x = 11
1 2 3 9 11 20 || i = 0,j = 4 sum = 11 x = 11
END
答案 13 :(得分:0)
不应该从两端迭代才能解决问题?
对数组进行排序。并从两端开始比较。
if((arr[start] + arr[end]) < sum) start++;
if((arr[start] + arr[end]) > sum) end--;
if((arr[start] + arr[end]) = sum) {print arr[start] "," arr[end] ; start++}
if(start > end) break;
时间复杂度O(nlogn)
答案 14 :(得分:0)
下面的代码将数组和数字N作为目标总和。 首先对数组进行排序,然后是一个包含该数组的新数组 拍摄剩余的元素,然后不通过二分搜索扫描 但同时对剩余部分和阵列进行简单扫描。
public static int solution(int[] a, int N) {
quickSort(a, 0, a.length-1); // nlog(n)
int[] remainders = new int[a.length];
for (int i=0; i<a.length; i++) {
remainders[a.length-1-i] = N - a[i]; // n
}
int previous = 0;
for (int j=0; j<a.length; j++) { // ~~ n
int k = previous;
while(k < remainders.length && remainders[k] < a[j]) {
k++;
}
if(k < remainders.length && remainders[k] == a[j]) {
return 1;
}
previous = k;
}
return 0;
}
答案 15 :(得分:0)
`package algorithmsDesignAnalysis;
public class USELESStemp {
public static void main(String[] args){
int A[] = {6, 8, 7, 5, 3, 11, 10};
int sum = 12;
int[] B = new int[A.length];
int Max =A.length;
for(int i=0; i<A.length; i++){
B[i] = sum - A[i];
if(B[i] > Max)
Max = B[i];
if(A[i] > Max)
Max = A[i];
System.out.print(" " + B[i] + "");
} // O(n) here;
System.out.println("\n Max = " + Max);
int[] Array = new int[Max+1];
for(int i=0; i<B.length; i++){
Array[B[i]] = B[i];
} // O(n) here;
for(int i=0; i<A.length; i++){
if (Array[A[i]] >= 0)
System.out.println("We got one: " + A[i] +" and " + (sum-A[i]));
} // O(n) here;
} // end main();
/******
Running time: 3*O(n)
*******/
}
答案 16 :(得分:0)
public static ArrayList<Integer> find(int[] A , int target){
HashSet<Integer> set = new HashSet<Integer>();
ArrayList<Integer> list = new ArrayList<Integer>();
int diffrence = 0;
for(Integer i : A){
set.add(i);
}
for(int i = 0; i <A.length; i++){
diffrence = target- A[i];
if(set.contains(diffrence)&&A[i]!=diffrence){
list.add(A[i]);
list.add(diffrence);
return list;
}
}
return null;
}
答案 17 :(得分:-1)
public static void Main(string[] args)
{
int[] myArray = {1,2,3,4,5,6,1,4,2,2,7 };
int Sum = 9;
for (int j = 1; j < myArray.Length; j++)
{
if (myArray[j-1]+myArray[j]==Sum)
{
Console.WriteLine("{0}, {1}",myArray[j-1],myArray[j]);
}
}
Console.ReadLine();
}