zoukankan      html  css  js  c++  java
  • 【leetcode】18 4 sum

    题目描述

    https://leetcode-cn.com/problems/4sum/description/
    给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。

    解法1

    本题是3sum的升级版,基本思路也与3sum差不多,首先对数组进行从小到大的排序,方便去重以及查找。
    然后对于前两个元素进行循环遍历,后两个元素则使用对撞指针的方法,从两个边界向内查找和等于target - a - b的结果。
    时间复杂度:O(n^3)

    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> res;
        if (nums.size() < 4)
        {
            return res;
        }
        sort(nums.begin(),nums.end());
    
        for (int i = 0; i < nums.size() - 3; i ++)
        {
            for (int j = i + 1; j < nums.size() - 2; j ++)
            {
                int sum = target - nums[i] - nums[j];
                /*
                 * 对撞指针
                 */
                int l = j + 1;//左边界
                int r = nums.size() - 1;//右边界
                while (l < r)
                {
                    if (nums[l] + nums[r] == sum){//满足条件
                        res.push_back({nums[i],nums[j],nums[l++],nums[r--]});
                        while(l < r && nums[r] == nums[r + 1])//右值去重
                            r --;
                        while(l < r && nums[l] == nums[l - 1])//左值去重
                            l ++;
                    }else if (nums[l] + nums[r] > sum)//和大于sum,则右边界向左移动
                    {
                        r --;
                    }else{//和小于sum,则左边界向右移动
                        l ++;
                    }
                }
                while(j < nums.size() - 2 && nums[j + 1] == nums[j])//去重
                    j ++;
            }
            while(i < nums.size() - 3 && nums[i + 1] == nums[i])//去重
                i ++;
        }
        return res;
    }
    

    在以上的基础上,可以对一些特殊情况添加判断以减少无效的循环遍历:

    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> res;
        if (nums.size() < 4)
        {
            return res;
        }
        sort(nums.begin(),nums.end());
    
        for (int i = 0; i < nums.size() - 3; i ++)
        {
            /*
             * 若当前值与最后三个最大值和仍小于target,则本轮不需要继续遍历了
             */
            if(nums[i] + nums[nums.size() - 1] + nums[nums.size() - 2] + nums[nums.size() - 3] < target)
                continue;
            /*
             * 若前四个最小值之和已经大于target了,则以后就不可能继续更小了,不需要继续遍历了
             */
            if(nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target)
                return res;
            for (int j = i + 1; j < nums.size() - 2; j ++)
            {
                /*
                 * 若前两个值与最后两个最大值的和仍小于target,则本轮不需要继续遍历了
                 */
                if(nums[i] + nums[j] + nums[nums.size() - 1] + nums[nums.size() - 2] < target)
                    continue;
                /*
                 * 若第一个值与第二层本轮循环前三个最小值之和已经大于target了,
                 * 则本轮循环以后就不可能继续更小了,则本轮循环不需要继续遍历了
                 */
                if(nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target)
                    break;
                int sum = target - nums[i] - nums[j];
                int l = j + 1;
                int r = nums.size() - 1;
                while (l < r)
                {
                    if (nums[l] + nums[r] == sum){
                        res.push_back({nums[i],nums[j],nums[l++],nums[r--]});
                        while(l < r && nums[r] == nums[r + 1])
                            r --;
                        while(l < r && nums[l] == nums[l - 1])
                            l ++;
                    }else if (nums[l] + nums[r] > sum)
                    {
                        r --;
                    }else{
                        l ++;
                    }
                }
                while(j < nums.size() - 2 && nums[j + 1] == nums[j])
                    j ++;
            }
            while(i < nums.size() - 3 && nums[i + 1] == nums[i])
                i ++;
        }
        return res;
    }
  • 相关阅读:
    Linux-diff命令
    Linux-查看文件内容命令
    Linux-tar命令
    Linux-df -h命令
    Linux-mkdir命令&touch命令
    Linux-cd命令&pwd命令
    Linux-zip命令&rz命令&sz命令
    Linux-npm install命令&脚本命令
    Linux-tail命令
    Linux-cat命令
  • 原文地址:https://www.cnblogs.com/JesseTsou/p/9515415.html
Copyright © 2011-2022 走看看