个人觉得最好理解的两种做法
两数之和
public static int[] twoSum(int[] nums, int target) {
if (nums != null) {
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] == target) {
return new int[]{i, j};
}
}
}
}
return null;
}
三树之和
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ret=new ArrayList<>();
Arrays.sort(nums);//排序
for(int i=0;i<nums.length;i++){//这里i是最小的数的下标
if(nums[i]>0){return ret;}//最小的数大于0,返回
if(i>0&&nums[i]==nums[i-1]){continue;}//去重,相同最小的数只能出现一次
int mid=i+1;//左边界(中间数)
int right=nums.length-1;//右边界(最大数)
while(mid<right){
int sum=nums[i]+nums[mid]+nums[right];
if(sum<0){mid++;}//三数之和小于0;将最小的下标后移
else if (sum>0){right--;}//三数之和大于0;将最大的下标前移
else {//三数之和等于0
ret.add(Arrays.asList(nums[i],nums[mid],nums[right]));
while(mid<right&&nums[mid+1]==nums[mid]){mid++;}//去重,相同中间数只能出现一次
while(mid<right&&nums[right-1]==nums[right]){right--;}//去重,相同最大数只能出现一次
mid++;right--;//去重后---> 中间,最后同时移动
}
}
}
return ret;
}
public List<List<Integer>> threeSum1(int[] nums) {
//思路分析,让我想到了,高中时学到的一种函数思想,固定一端,保持递增,另一端,采用双指针移动进行循环匹对,力扣有查询时间限制,过滤条件一个都不能省
List<List<Integer>> ans = new ArrayList<>();
Arrays.sort(nums); // 先升序排序
for (int i = 0; i < nums.length; i++) {
if (nums[i] > 0) {//因为排过序了,如果i对应的肯定是最小的,如果最小的都大于0,总数肯定大于0
return ans;
}
if (i > 0 && nums[i] == nums[i - 1]) { //最左端的去重
continue;
}
int j = i + 1; //j 相当于左指针
int k = nums.length - 1; // k相当于右指针
while (j < k) { // 在左指针和右指针第一次相遇前做判断
int sum = nums[i] + nums[j] + nums[k];
if (sum < 0) {//和小于0就把中间指针往后移
j++;
}
if (sum > 0) {//和大于0就把最后指针往前移
k--;
}
if (sum == 0) {//和等于0就和前面的值比较去重,同时进行下一次循环
ans.add(Arrays.asList(nums[i], nums[j], nums[k]));
while (j<k&& nums[j] == nums[j + 1]) {//中指针去重
j++;
}
while (j<k&&nums[k - 1] == nums[k]) {//右指针去重
k--;
}
j++;
k--;
}
}
}
return ans;
}