NC61:两数之和
两数之和
http://www.nowcoder.com/questionTerminal/20ef0972485e41019e39543e8e895b7f
1.NC61:两数之和:
给出一个整数数组,请在数组中找出两个加起来等于目标值的数,你给出的函数twoSum 需要返回这两个数字的下标(index1,index2),需要满足 index1 小于index2
注意:下标是从1开始的,假设给出的数组中只存在唯一解
给出的数组为 {2, 7, 11, 15},目标值为9 输出 ndex1=1, index2=2
解法1:暴力求解:
第一层遍历每个数,在遍历每个数的同时,遍历其他的数是不是他的补(target-self, complement)
public class Solution { public int[] twoSum(int[] numbers, int target) { for(int i=0;i<numbers.length;i++){ for(int j=i+1;j<numbers.length;j++){ if(numbers[i]+numbers[j]==target){ return new int[]{i+1,j+1}; } } } return null; } }
解法2:哈希表
时间复杂度为 O(N),空间复杂度为 O(N),使用空间来换取时间。
- 首先我们定义一个哈希表map后,我们就将number[i]进行标记,即map[number[i]]=i
- 然后我们使用一层for循环查询map里面有没有target-number[i]
- 如果有就返回map[target- number[i]] + 1和i + 1
- 如果没有就查询下一个
import java.util.HashMap; public class Solution { public int[] twoSum(int[] numbers, int target) { HashMap<Integer,Integer> map=new HashMap<>(); for(int i=0;i<numbers.length;i++){ if(map.containsKey(target-numbers[i])){ return new int[]{map.get(target-numbers[i])+1,i+1}; } else{ map.put(numbers[i],i); } } return null; } }
2.三数之和:
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。注意:答案中不可以包含重复的三元组。
给定数组 nums = [-1, 0, 1, 2, -1, -4], 满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]
思路:标签:数组遍历
首先对数组进行排序,排序后固定一个数 nums[i],再使用左右指针指向 nums[i]后面的两端,数字分别为 nums[L] 和 nums[R],计算三个数的和 sum 判断是否满足为 0,满足则添加进结果集
如果 nums[i]大于 0,则三数之和必然无法等于 0,结束循环
如果 nums[i] == nums[i−1],则说明该数字重复,会导致结果重复,所以应该跳过
当 sum == 0 时,nums[L] == nums[L+1] 则会导致结果重复,应该跳过,L++
当 sum == 0 时,nums[R] == nums[R−1] 则会导致结果重复,应该跳过,R−−
时间复杂度:O(n2),n 为数组长度
import java.util.*; public class Solution { public ArrayList<ArrayList<Integer>> threeSum(int[] num) { ArrayList<ArrayList<Integer>> res=new ArrayList<>(); if(num==null || num.length<3){ return res; } Arrays.sort(num);// 排序 for(int i=0;i<num.length-2;i++){ if(num[i]>0){ break;// 如果当前数字大于0,则三数之和一定大于0,所以结束循环 } if(i>0 && num[i]==num[i-1]){ continue;// 去重 } int L=i+1; int R=num.length-1; while(L<R){ int sum=num[i]+num[L]+num[R]; if(sum==0){ //res.add(new ArrayList<>(Arrays.asList(num[i],num[L],num[R]))) ArrayList<Integer> list=new ArrayList<>(); list.add(num[i]); list.add(num[L]); list.add(num[R]); res.add(list); while(L<R && num[L]==num[L+1]){ L++;// 去重 } while(L<R && num[R]==num[R-1]){ R--;// 去重 } L++; R--; } else if(sum>0){ R--; } else if(sum<0){ L++; } } } return res; } }
3.四数之和:
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c+ d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:答案中不可以包含重复的四元组。
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。 满足要求的四元组集合为: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
与3sum思路类似,只不过这次需要先固定两个数,然后双指针找,用set去除重复组合
import java.util.ArrayList; import java.util.Arrays; public class Solution { public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) { ArrayList<ArrayList<Integer>>res = new ArrayList<>(); if(num==null||num.length<4)return res; Arrays.sort(num); for(int i=0;i<num.length-3;i++){ if(num[i]+num[i+1]+num[i+2]+num[i+3]>target)break; if(num[i]+num[num.length-3]+num[num.length-2]+num[num.length-1]<target)continue; for(int j=i+1;j<num.length-2;j++){ int k = j+1; int l = num.length-1; while(k<l){ if(num[i]+num[j]+num[k]+num[l]==target){ ArrayList<Integer>tmp = new ArrayList<>(); tmp.add(num[i]); tmp.add(num[j]); tmp.add(num[k]); tmp.add(num[l]); k++; l--; if(!res.contains(tmp)) res.add(tmp); }else if(num[i]+num[j]+num[k]+num[l]>target){ l--; }else k++; } } } return res; } }
牛客题霸 - 程序员面试高频题 - 题解