问题:
快速找出一个数组中的两个数字,使两个数字之和为一个特定的值。假设数组中至少存在一组符合要求的解。
分析与解法:
【解法一】
穷举,从数组中任意选取两个数字,计算两个数字之和是否等于给定的数字。时间复杂度为O(n^2)。
【解法二】
对数组中的每个数arr[i]都判定sum-arr[i]是否在数组中,于是题目就变成了一个查找算法。可以先对数组进行排序,再使用二分法进行查找,总的时间复杂度为O(2*nlogn)。
【解法三】
使用空间换时间的方法,使用hash表。对每个数arr[i]在表中查找sum-arr[i],每次查找时间复杂度为O(1),总的时间复杂度为O(n)。
代码:
void find(int[] arr, int sum, int n){
int[] index = new int[2];
index[0] = -1;
index[1] = -1;
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < n; i++){
if(map.containsKey(sum - arr[i]) == false){
map.put(arr[i], i);
}
else{
index[0] = map.get(sum - arr[i]);
index[1] = i;
System.out.println(index[0] + " " + index[1]);
}
}
System.out.println(index[0] + " " + index[1]);
}
【解法四】
先对数组进行排序,时间复杂度为O(nlogn),再使用双游标的方法分别从有序数组的前后对数组之和进行扫描,时间复杂度为O(n),总的时间复杂度为O(nlogn)。
代码:
/*在有序数组中查找和为sum的两个数*/
void find(int arr[], int sum, int n)
{
int i, j;
i = 0;
j = n - 1;
while(i < j)
{
if(arr[i] + arr[j] < sum)
i++;
else if(arr[i] + arr[j] > sum)
j--;
else
cout << i << "," << j;
}
}
扩展问题:
1.如果问题中“两个数字”改为“三个数字”或“任意个数字”该如何求解?
分析与解法:
1.属于动态规划的背包问题。需要考虑放和不放两种情况。
代码:
http://blog.csdn.net/wuzhekai1985/article/details/6728657