1. 两数之和
这道题可以暴力也可以用哈希。
首先来说暴力,就是两个嵌套的循环,找到的第一个相加为target的一组数返回。
哈希就相对复杂一点。当然大家可能会有疑问,什么时候使用哈希,使用哪种哈希?每当我们遇到要判断这种元素是否出现过时,就可以使用哈希,具体使用哪种可以看我之前的文章。对于本题,我们要找到和为目标值的数的下标,首先找到这两个数,再找到下标,相当于key和value,且key不能重复,所以要使用HashMap。代码如下
java
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map=new HashMap<>();
for(int i=0;i<nums.length;i++){
int s=target-nums[i];
if(map.containsKey(s)){
return new int[]{map.get(s),i};
}
map.put(nums[i],i);
}
return new int[0];
}
}
令s=target-nums[i],查询map中是否有nums[i]的另一半,如果有就返回,如果没有就存到map中继续向后循环。
454. 四数相加 II
这道题一个暴力的思路是四个for循环,但这样太麻烦了,我们依然可以使用哈希表。这道题可能出现很大的数,因此不能用数组。又因为我们不仅要统计这个数是否出现过,还要统计出现的次数,因此还是用HashMap。代码如下
java
class Solution {
public int fourSumCount(int[] A, int[] B, int[] C, int[] D) {
Map<Integer,Integer> map=new HashMap<>();
int count=0;
for(int a:A){
for(int b:B){
map.put(a+b,map.getOrDefault(a+b,0)+1);
}
}
for(int c:C){
for(int d:D){
if(map.containsKey(-c-d)){
count+=map.get(-c-d);
}
}
}
return count;
}
}
我们先将a、b两个数组的数相加,存到map中,如果有重复的就让value的值加一。之后让c、d两个数组的值相加,判断map中是否有-(c+d)的值,如果有就让次数加上value。
我们要找的是a+b+c+d=0,所以a+b=-(c+d),因此找-(c+d),又因为不需要去重,所以次数加的是value的。
15. 三数之和
这道题也可以用哈希来做,但比较复杂,我们可以使用双指针的方法。我们需要在一个数组里找出三个数相加等于0,且不能重复。

我们可以建立一个for循环,之后创建两个指针,不过前提是将他们升序排列。如果nums[i]>0,则直接退出循环。之后就看nums[i]+nums[left]+nums[right]的值,如果大于0,就让right--,如果小于0,就让left++。又因为不能重复,所以nums[i]如果和nums[i-1]相等的话,则要跳过这一次循环,left和right也是一样。代码如下
java
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> ans=new ArrayList<List<Integer>>();
for(int i=0;i<nums.length;i++){
if(nums[i]>0)
break;
if(i>0&&nums[i]==nums[i-1])
continue;
int left=i+1;
int right=nums.length-1;
while(right>left){
if(nums[i]+nums[left]+nums[right]>0){
right--;
}else if(nums[i]+nums[left]+nums[right]<0){
left++;
}else{
List<Integer> list=new ArrayList<Integer>();
list.add(nums[i]);
list.add(nums[left]);
list.add(nums[right]);
ans.add(list);
while(right>left&&nums[right]==nums[right-1]){
right--;
}
while(left<right&&nums[left]==nums[left+1]){
left++;
}
left++;
right--;
}
}
}
return ans;
}
}
18. 四数之和
这题跟三数之和很相似,只不过多了一个数,那我们就用两个循环。

代码如下。
java
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> ans=new ArrayList<List<Integer>>();
for(int i=0;i<nums.length;i++){
for(int k=i+1;k<nums.length;k++){
if((nums[i]>target&&target>0)||(nums[i]+nums[k]>target&&target>0))
break;
if((i>0&&nums[i]==nums[i-1])||(k>i+1&&nums[k]==nums[k-1]))
continue;
int left=k+1;
int right=nums.length-1;
while(right>left){
if((long)nums[i]+nums[left]+nums[right]+nums[k]>target){
right--;
}else if((long)nums[i]+nums[left]+nums[right]+nums[k]<target){
left++;
}else{
List<Integer> list=new ArrayList<Integer>();
list.add(nums[i]);
list.add(nums[k]);
list.add(nums[left]);
list.add(nums[right]);
ans.add(list);
while(right>left&&nums[right]==nums[right-1]){
right--;
}
while(left<right&&nums[left]==nums[left+1]){
left++;
}
left++;
right--;
}
}
}
}
return ans;
}
}