解法一:暴力破解(穷举法,不提倡)
(穷举,时间复杂度:O(n^2),正常是不会用这个滴,假如只是为了快速解题,对时间没有限制,用这个最简单)
//暴力枚举法
function getSum1(arr,sum) {
//去掉数组中的重复元素
var items = new Set(arr);
arr = Array.from(items);
console.log(arr)
for(var i=0;i<arr.length;i++)
for(var j=i+1;j<arr.length;j++){
if(arr[i]+arr[j]===sum){
console.log(arr[i]+"+"+arr[j]);
}
}
}
var arr =[2,1,8,-2,-7,-1,-2,-8];
getSum1(arr,0);
解法二:二分法(相当于用两个指针)
两个指针二分查找
(排序时间复杂度为O(nlog(n)),while最多O(N),所以最终程序的时间复杂度为:O(nlo(n)))
//排序二分查找法
function getSum2(arr,sum) {
//数组排序
arr.sort(function (a,b) {
return a-b;//必须指定排序函数,否则按照字符升序排序
});
//去掉数组中的重复元素
var items = new Set(arr);
var arr2 = Array.from(items);
console.log(arr2);
var left=0,right =arr2.length-1;
while(left<right){
if(arr2[left]+arr2[right]>sum){
right--;
}else if(arr2[left]+arr2[right]<sum){
left++;
}else if(arr2[left]+arr2[right]==sum){
console.log(arr2[left]+" + "+arr2[right]+"="+sum);//常犯错误,将变量名写错,arr2写成arr
left++;
right--;
}
}
}
//getSum2(arr,0);
关键点:1.数组排序,2.去重,3.2分查找
扩展为3个元素
参考:http://blog.csdn.net/tonghuawanli/article/details/61196462
http://blog.csdn.net/vvaaiinn/article/details/45220443
public static ArrayList<ArrayList<Integer>> threeSum(int[] num)
{
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
if(num == null||num.length<3)//如果只有2个数字 或者为空 返回空
return res;
Arrays.sort(num);
for(int i = 0; i<num.length -2;i++)// 保证最后得有num.length-1 和num.length-2两个数,才可以进循环
{
if(i > 0 && num[i] == num[i-1])//如果要是有重复的直接跳过。
continue;
ArrayList<ArrayList<Integer>> cur = twoSum(num,i+1,-num[i]); //得到当前数字可以组合出来的数字序列的子集。
res.addAll(cur);
}
return res;
}
public static ArrayList<ArrayList<Integer>>twoSum (int []num,int start,int target)
{
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
if(num == null||num.length < 2)
return res;
int l = start;//起始位置
int pri = start-1;//当前数字
int r = num.length-1;//终止位置
while(l < r)//采用夹逼,逼近target
{
if(num[l]+num[r] == target)//
{
ArrayList<Integer> te = new ArrayList<Integer>();//符合的话 把三个数放入到list中
te.add(num[pri]);
te.add(num[l]);
te.add(num[r]);
res.add(te);
int k = l + 1;//从l的下一个开始 去除重复。
while(k < r&& num[k] == num[l])
k++;
l = k;
k = r - 1;//去除R的重复
while(k > l &&num[k] == num[r])
k--;
r = k;
}
else if(num[l] + num[r] > target)//夹逼
r--;
else l++;
}
return res;
}
两个元素求和:
参考(java版): http://blog.csdn.net/qyys20/article/details/53349558
两种方法(1.二分查找;2.hash表;两种方法时间复杂度都为O(n),但第一种空间复杂度为O(1),第二种为O(n)) http://www.cnblogs.com/hapjin/p/5746659.html