代码随想录Day12-哈希表&字符串:力扣第15、18、344题

15. 三数之和

题目链接
代码随想录文章讲解链接

方法一:排序+左右双指针

用时:1h10m31s

思路

1)排序:首先对数组进行排序。
2)双指针:定一找二。
设“三数”分别为a、b、c,依次遍历数组中的每个数字,作为a,即“定一”,注意移动a的过程时候要一直移动到不重复的数为止,防止结果重复;
然后对a右边的数组使用双指针,即“找二”,双指针的起始位置为a的右边第一个数b以及数组最后一个数c,双指针向中间走。如果当前三数之和小于0,则b向右移,因为数组排序过了,只有b向右移才有可能等于0;如果和大于0,则c向左移,理由类似;如果和等于0,则记录结果,并将b向右移,c向左移,注意此处需要一直移动到出现新的数字,以防结果重复。

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( log ⁡ n ) O(\log{n}) O(logn),排序需要的空间。
C++代码
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int size = nums.size();
        vector<vector<int>> res;

        sort(nums.begin(), nums.end());
        for (int i = 0; i < size - 2; ++i) {
            // 如果第一个数字都大于0,那么三数之和就不可能等于0
            if (nums[i] > 0) return res;
            // 防止出现重复的三元组
            if (i > 0 && nums[i] == nums[i - 1]) continue;

            int left = i + 1;
            int right = size - 1;
            while (left < right) {
                int sum = nums[i] + nums[left] + nums[right];
                if (sum < 0) ++left;
                else if (sum > 0) --right;
                else {
                    res.push_back({nums[i], nums[left], nums[right]});
                    while (left < right && nums[left] == nums[left + 1]) ++left;
                    while (left < right && nums[right] == nums[right - 1]) --right;
                    ++left;
                    --right;
                }
            }
        }
        return res;
    }
};

看完讲解的思考

注意去重。

代码实现遇到的问题

一开始被代码随想录坑了,想着用哈希表实现,结果搞了一个钟都搞不出来,这题感觉就不应该用哈希表来做啊!后面用双指针一下就做出来,不过做的时候还是有些小bug,忘记去重,结果要求是不重复的组合。


18. 四数之和

题目链接
代码随想录文章讲解链接

方法一:排序+左右双指针

用时:19m6s

思路

与上一题类似,多一层for循环

  • 时间复杂度: O ( n 3 ) O(n^3) O(n3)
  • 空间复杂度: O ( log ⁡ n ) O(\log{n}) O(logn)
C++代码
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        int size = nums.size();
        vector<vector<int>> res;

        sort(nums.begin(), nums.end());
        for (int i = 0; i < size - 3; ++i) {
            // 如果第一个数已经大于target,则直接返回结果
            if (nums[i] > target && nums[i] >= 0) break;
            // 防止重复的四元组
            if (i > 0 && nums[i] == nums[i - 1]) continue;

            for (int j = i + 1; j < size - 2; ++j) {
                // 同上
                if (nums[i] + nums[j] > target && nums[i] + nums[j] >= 0) break;
                if (j > i + 1 && nums[j] == nums[j - 1]) continue;

                int left = j + 1;
                int right = size - 1;
                while (left < right) {
                    long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];
                    if (sum < target) ++left;
                    else if (sum > target) --right;
                    else {
                        res.push_back({nums[i], nums[j], nums[left], nums[right]});
                        // 去重
                        while(left < right && nums[left] == nums[left + 1]) ++left;
                        while(left < right && nums[right] == nums[right - 1]) --right;
                        ++left;
                        --right;
                    }
                }
            }
        }
        return res;
    }
};

看完讲解的思考

无。

代码实现遇到的问题

  • 一开始其实想到了这么做,但是想着时间复杂度是 O ( n 3 ) O(n^3) O(n3),觉得不可能是最优解,想来想去想不到更好的解法,结果一看题解还真是这样。
  • int溢出了,没有注意数组元素的取值范围,以后一定要注意!

344. 反转字符串

题目链接
代码随想录文章讲解链接

方法一:左右双指针

用时:2m

思路

左右双指针,交换。

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)
C++代码
class Solution {
public:
    void reverseString(vector<char>& s) {
        int left = 0;
        int right = s.size() - 1;
        while (left < right) swap(s[left++], s[right--]);
    }
};

看完讲解的思考

无。

代码实现遇到的问题

无。


最后的碎碎念

21点才开始刷,结果整到了23点,溜了溜了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值