算法——双指针(day4)

15.三数之和

 

15. 三数之和 - 力扣(LeetCode) 

题目解析:

这道题目说是三数之和,其实这和我们之前做过的两数之和是一个规律的~无非就是我们需要实时改动target的值。先排好序,然后固定一个数取其负值作target,然后我们再从除固定数以外的范围内寻找两数之和为target的数,这样再与固定数相加就得到0了,形成三元数组。

 

算法解析:

这就是两数和的核心图解,唯一区别就是我们的target值是随着固定数的变化而发生改变的~

废话不多说,本题的难点就在于去重以及去重时的越界问题。因为按照题目规定类似于

【-1,0,-1】与【-1,-1,0】这种会算重复项只能取其一,而这也是我们优先选择排序的原因,在排行序后二者就变为【-1,-1,0】,更容易去重。

去重分两个阶段,一是【left,right】范围之间的去重,另一个是固定数first遍历数组的去重。

所以我们给出的去重方案就是观察移动前后的数值是否相同,如果相同那就再移动一位,直到不同为止。不过这样也引发了新的问题:越界~

 

我们发现left与right的选取是需要在【left,rigtht】这个界限里面的所以只需要加上一层条件即可(left<right)~

 固定数first同理:

代码: 


class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> ret;
        sort(nums.begin(), nums.end());
        int n = nums.size();
        int first = 0;
        while (first <= n - 3)
        {
            //小优化
            if (nums[first] > 0) break;
            int left = first + 1;
            int right = n - 1;
            int target = -nums[first];
            //一轮比较
            while (left < right)
            {
                int sum = nums[left] + nums[right];
                if (sum > target)
                {
                    --right;
                }
                else if (sum < target)
                {
                    ++left;
                }
                else
                {
                    ret.push_back({ nums[first],nums[left],nums[right] });
                    right--;
                    left++;
                    //left与right去重
                    while (left < right && nums[right + 1] == nums[right])
                    {
                        right--;
                    }
                    while (left < right && nums[left - 1] == nums[left])
                    {
                        left++;
                    }
                }

            }
            //固定数去重
            first++;
            while (first < n && nums[first - 1] == nums[first])
            {
                first++;
            }

        }
        return ret;
    }
};

18.四数之和

18. 四数之和 - 力扣(LeetCode)

题目解析:

四数之和别看多了一个数,其实和三数之和还是同一个模板,没有本质区别

算法解析:

 

找四数之和我们可以先拆分成固定数a与三数之和,那么三数之和的值就得为target-a。这样a与三数之和才相加才可以变为target,而在三数之和中就得拆分成固定数b与两数之和,那么两数之和的值就得为target-a-b,这样才能与b相加得到target-a。

所以只要在三数之和的代码中把控好target-a-b的值就行了,除此之外再多加一个对固定数a的去重就好了~

 代码:

在三数之和外套一层固定数a的循环以及去重复,另外改变目标值t变为target-a-b就差不多了。


class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> ret;
        sort(nums.begin(), nums.end());
        int n = nums.size();
        int a = 0;
        //固定数a
        while (a <= n - 4)
        {
            //固定数b
            int b = a + 1;
            while (b <= n - 3)
            {
                int left = b + 1;
                int right = n - 1;
                //防止数据溢出强转类型
                long long t = (long long)target - nums[b] - nums[a];
                while (left < right)
                {
                    int sum = nums[left] + nums[right];
                    if (sum > t)
                    {
                        --right;
                    }
                    else if (sum < t)
                    {
                        ++left;
                    }
                    else
                    {
                        ret.push_back({ nums[a],nums[b],nums[left],nums[right] });
                        right--;
                        left++;
                        //一级去重复
                        while (left < right && nums[right + 1] == nums[right])
                        {
                            right--;
                        }
                        while (left < right && nums[left - 1] == nums[left])
                        {
                            left++;
                        }
                    }

                }
                //二级去重
                b++;
                while (b < n && nums[b - 1] == nums[b])
                {
                    b++;
                }

            }
            //三级去重
            a++;
            while (a < n && nums[a - 1] == nums[a])
            {
                a++;
            }

        }
        return ret;
    }
};

 

相关推荐

  1. 算法训练day10字符串总结指针回顾

    2024-07-19 20:08:02       52 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-19 20:08:02       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-19 20:08:02       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-19 20:08:02       58 阅读
  4. Python语言-面向对象

    2024-07-19 20:08:02       69 阅读

热门阅读

  1. 关于二进制和八进制

    2024-07-19 20:08:02       15 阅读
  2. Linux 和 Unix 系统中非常流行文本处理工具awk

    2024-07-19 20:08:02       15 阅读
  3. 专升本-1.0.4(英语)-升本208天-学习成果展示

    2024-07-19 20:08:02       17 阅读
  4. 1818:ATP

    2024-07-19 20:08:02       21 阅读
  5. 使用容器化技术部署淘客返利系统的实践与挑战

    2024-07-19 20:08:02       18 阅读
  6. 【WiFi】DFS Vs ZW-DFS

    2024-07-19 20:08:02       16 阅读
  7. 蓝牙新篇章:WebKit的Web Bluetooth API深度解析

    2024-07-19 20:08:02       23 阅读
  8. Solana开发之Anchor框架-部署到 Devnet

    2024-07-19 20:08:02       17 阅读
  9. 快速上手绿联私有云UGOS Pro系统Docker

    2024-07-19 20:08:02       20 阅读
  10. 跟ChatGPT学习go语言--int 类型如何转化成string

    2024-07-19 20:08:02       17 阅读