题目要求:给定一个nums数组,要求找出全部的满足四数之和等于给定target的数组元素组合,且这些组合中的元素不能重复。
我的思路:用四个指针,两个指针left和right从数组两端往数组中间靠近,目的是为了确定四个数中的两个数。另外两个指针low和high在left和right之间,目的是为了在确定了left和right的时候看能否找到另外两个数,能够满足题目要求。
具体实现步骤:1.用一个list来装要返回的全部数组元素组合
2.判断nums是否为空,或者长度是否小于4,如果是的话,直接返回元素为空的list
3.首先将left设为0,rigjht设为nums.length-1,分别指向 一头一尾
4.只要right-left>=3,说明从left到right的数组元素个数大于等于4,有必要进行循环,否则没必要
5.固定right和left,并且用l和r来记录当前的left和right,方便后来right和left指针移动之后用;现在,需要确定在left和right之间能否找到两个数,使得这两个数的和加上nums[left]和nums[right]等于target,于是调用process方法进行判断
6.现在固定left指针,让right指针移动到不重复的元素的位置,在right-left>=3的情况下继续调用process函数确定在left和right之间能否找到两个数,使得这两个数的和加上nums[left]和nums[right]等于target,于是调用process方法进行判断
7.将right指针置为r,让它回到原来的位置,然后left指针移动到不重复的元素的位置,在right-left>=3的情况下继续调用process函数确定在left和right之间能否找到两个数,使得这两个数的和加上nums[left]和nums[right]等于target,于是调用process方法进行判断
8.再将left指针重新置为l,left指针与right指针同时移动到不重复元素的位置,继续5.6.7操作
process函数要做的其实就是看在low和high之间能不能找到满足两数之和等于target-nums[right]-nums[left]的两个数,找到了就把这四个数加进list,没找到就不加。其实可以借鉴两数之和的代码来写。但是要注意的是,在两数之和这道题目中,利用HashMap解题并没有考虑到重复性问题,因为它的题目本身就只要求返回两个数就可以了。因此,考虑到重复性的问题,这个问题仍然可以用双指针来做。
class Solution {
public void process(int[]nums,int target,int left,int right,ArrayList<List<Integer>>list){
int low=left+1,high=right-1;
while(low<high){
int sum=nums[left]+nums[right]+nums[low]+nums[high];
if(sum==target){
list.add(Arrays.asList(nums[left],nums[low],nums[high],nums[right]));
low++;
high--;
while(low<high&&nums[low]==nums[low-1]){
low++;
}
while(low<high&&nums[high]==nums[high+1]){
high--;
}
}else if(sum<target){
low++;
while(low<high&&nums[low]==nums[low-1]){
low++;
}
}else{
high--;
while(low<high&&nums[high]==nums[high+1]){
high--;
}
}
}
}
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
ArrayList<List<Integer>>list=new ArrayList<List<Integer>>();
if(list==null||nums.length<4){//判断nums是否为空,或者长度是否小于4,如果是的话,直接返回元素为空的list
return list;
}
int left=0,right=nums.length-1,l=0,r=nums.length-1;
while(right-left>=3){
l=left;
r=right;
process(nums,target,left,right,list);//固定right和left,并且用l和r来记录当前的left和right,方便后来right和left指针移动之后用;现在,需要确定在left和right之间能否找到两个数,使得这两个数的和加上nums[left]和nums[right]等于target,于是调用process方法进行判断
right--;//现在固定left指针,让right指针移动到不重复的元素的位置,在right-left>=3的情况下继续调用process函数确定在left和right之间能否找到两个数,使得这两个数的和加上nums[left]和nums[right]等于target,于是调用process方法进行判断
while(left<right&&nums[right]==nums[right+1]){
right--;
}
while(right-left>=3){
process(nums,target,left,right,list);
right--;
while(left<right&&nums[right]==nums[right+1]){
right--;
}
}
right=r;//.将right指针置为r,让它回到原来的位置,然后left指针移动到不重复的元素的位置,在right-left>=3的情况下继续调用process函数确定在left和right之间能否找到两个数,使得这两个数的和加上nums[left]和nums[right]等于target,于是调用process方法进行判断
left++;
while(left<right&&nums[left]==nums[left-1]){
left++;
}
while(right-left>=3){
process(nums,target,left,right,list);
left++;
while(left<right&&nums[left]==nums[left-1]){
left++;
}
}
left=l;//再将left指针重新置为l,left指针与right指针同时移动到不重复元素的位置
left++;
right--;
while(left<right&&nums[left]==nums[left-1]){
left++;
}
while(left<right&&nums[right]==nums[right+1]){
right--;
}
}
return list;
}
}
四数之和
原文:https://www.cnblogs.com/xbc121/p/11873468.html