双指针解决n数之和问题

1. 两数之和

1. 两数之和

  • 将时间复杂度降到O(n);
class Solution {
    
    
    // 双指针
    public int[] twoSum(int[] nums, int target) {
    
    
        int n=nums.length;
        int l=0;
        while(l<n){
    
    
            int r=n-1;
            // 找到第一个可能nums[l]+nums[r]==target的位置
            while(r>l){
    
    
                if(nums[l]+nums[r]==target){
    
    
                    return new int[]{
    
    l,r};
                }
                r--;
            }
            l++;
        }
        return new int[0];
    }
}
class Solution {
    
    
    // 哈希表 
    public int[] twoSum(int[] nums, int target) {
    
    
        int n=nums.length;
        HashMap<Integer,Integer> map=new HashMap<>();
        for(int i=0;i<n;i++){
    
    
            map.put(nums[i],i);
        }
        for(int i=0;i<n;i++){
    
    
            int another=target-nums[i];
            if(map.containsKey(another)&&map.get(another)!=i){
    
    
                return new int[]{
    
    i,map.get(another)};
            }
        }
        return new int[0];
    }
}

2. 两数之和 II - 输入有序数组

167. 两数之和 II - 输入有序数组

  • 将时间复杂度降到O(n);
class Solution {
    
    
    // 双指针
    public int[] twoSum(int[] numbers, int target) {
    
    
        int n=numbers.length;
        int l=0;
        while(l<n){
    
    
            int r=n-1;
            // 找到第一个可能nums[l]+nums[r]==target的位置
            while(r>l){
    
    
                if(numbers[l]+numbers[r]==target){
    
    
                    return new int[]{
    
    l+1,r+1};
                }
                r--;
            }
            l++;
        }
        return new int[0];
    }
}
class Solution {
    
    
    // 双指针
    public int[] twoSum(int[] numbers, int target) {
    
    
        int l=0,r=numbers.length-1;
        while(l<r){
    
    
            if(numbers[l]+numbers[r]>target){
    
    
                r--;
            }else if(numbers[l]+numbers[r]<target){
    
    
                l++;
            }else{
    
    
                return new int[]{
    
    l+1,r+1};
            }
        }
        return new int[0];
    }
}

3. 三数之和

15. 三数之和
剑指 Offer II 007. 数组中和为 0 的三个数

  • 将时间复杂度降到O(n2);
class Solution {
    
    
    // 排序+双指针
    // a+b+c=0  ---> a=-(b+c)
    public List<List<Integer>> threeSum(int[] nums) {
    
    
        // 排序保证重复元素连续
        Arrays.sort(nums);
        List<List<Integer>> ans=new ArrayList<>();
        int n=nums.length;
        int a=0;  // 确定第一个数
        while(a<n){
    
    
            // 分别确定第二、三个数
            int c=n-1;
            int b=a+1;
            while(b<n){
    
    
                while(c>b&&(-nums[a]<nums[b]+nums[c])){
    
    
                    c--;
                }
                if(c==b){
    
    
                    break;
                }
                if(-nums[a]==nums[b]+nums[c]){
    
      // a+b+c=0  可行解
                    List<Integer> cur=new ArrayList<>();
                    cur.add(nums[a]);
                    cur.add(nums[b]);
                    cur.add(nums[c]);
                    ans.add(cur);
                }
                // 找到下一个与b不重复的元素
                int d=b+1;
                while(d<n&&nums[d]==nums[b]){
    
    
                    d++;
                }
                b=d;
            }
            // 找到下一个与a不重复的元素
            int e=a+1;
            while(e<n&&nums[e]==nums[a]){
    
    
                e++;
            }
            a=e;
        }
        return ans;
    }
}
class Solution {
    
    
    // 排序+双指针
    // a+b+c=0  ---> a=-(b+c)
    public List<List<Integer>> threeSum(int[] nums) {
    
    
        // 排序保证重复元素连续
        Arrays.sort(nums);
        List<List<Integer>> ans=new ArrayList<>();
        int n=nums.length;
        int a=0;  // 确定第一个数
        while(a<n){
    
    
            // 找到下一个与a不重复的元素
            if(a==0||nums[a]!=nums[a-1]){
    
    
                // 确定第二个数
                int b=a+1;
                int c=n-1;
                while(b<n){
    
    
                    // 找到下一个与b不重复的元素
                    if(b==a+1||nums[b]!=nums[b-1]){
    
    
                        // 确定第三个数
                        while(c>b&&(nums[a]+nums[b]>-nums[c])){
    
    
                            c--;
                        }
                        if(c==b){
    
    
                            break;
                        }
                        if(nums[a]+nums[b]==-nums[c]){
    
      // a+b+c=0  可行解
                            List<Integer> cur=new ArrayList<>();
                            cur.add(nums[a]);
                            cur.add(nums[b]);
                            cur.add(nums[c]);
                            ans.add(cur);
                        }
                    }
                    b++;
                }
            }
            a++;
        }
        return ans;
    }
}

4. 四数之和

18. 四数之和

  • 将时间复杂度降到O(n3);
class Solution {
    
    
    // 排序+双指针
    public List<List<Integer>> fourSum(int[] nums, int target) {
    
    
        Arrays.sort(nums);
        List<List<Integer>> ans=new ArrayList<>();
        int n=nums.length;
        // 第一个数
        int a=0;
        while(a<n){
    
    
            if(a==0||(nums[a]!=nums[a-1])){
    
    
                // 第二个数
                int b=a+1;
                while(b<n){
    
    
                    if(b==a+1||(nums[b]!=nums[b-1])){
    
    
                        // 第三个数
                        int c=b+1;
                        // 第四个数
                        int d=n-1;
                        while(c<n){
    
    
                            if(c==b+1||(nums[c]!=nums[c-1])){
    
    
                                long sum=nums[a]+nums[b]+nums[c]-target;
                                // 第四个数
                                while(d>c&&((long)nums[a]+nums[b]+nums[c]+nums[d]>target)){
    
    
                                    d--;
                                }
                                if(d==c){
    
    
                                    break;
                                }
                                // 可行解
                                if((long)nums[a]+nums[b]+nums[c]+nums[d]==target){
    
    
                                    List<Integer> cur=new ArrayList<>();
                                    cur.add(nums[a]);
                                    cur.add(nums[b]);
                                    cur.add(nums[c]);
                                    cur.add(nums[d]);
                                    ans.add(cur);
                                }
                            }
                            c++;
                        }
                    }
                    b++;
                }
            }
            a++;
        }
        return ans;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_43665602/article/details/131971226
今日推荐