代码随想录算法训练营第2天|977. 有序数组的平方、209.长度最小的子数组、59. 螺旋矩阵II

代码随想录算法训练营第2天|977. 有序数组的平方、209.长度最小的子数组、59. 螺旋矩阵II

977. 有序数组的平方

题目链接

提交代码(双指针)
class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int len = nums.size();
        int left = 0;
        int right = len - 1;
        vector<int> result;
        while(left <= right)
        {
            if(nums[left] * nums[left] >= nums[right] * nums[right])
            {
                result.push_back(nums[left] * nums[left]);
                left++;
            }
            else
            {
                result.push_back(nums[right] * nums[right]);
                right--;
            }
        }
        reverse(result.begin(), result.end());
        return result;
    }
};
解答代码(方法1-直接平方再排序时间复杂度是nlogn)
class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        vector<int> ans;
        for (int num: nums) {
            ans.push_back(num * num);
        }
        sort(ans.begin(), ans.end());
        return ans;
    }
};
解答代码(方法2-双指针(n))
class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int n = nums.size();
        int negative = -1;
        for (int i = 0; i < n; ++i) {
            if (nums[i] < 0) {
                negative = i;
            } else {
                break;
            }
        }

        vector<int> ans;
        int i = negative, j = negative + 1;
        while (i >= 0 || j < n) {
            if (i < 0) {
                ans.push_back(nums[j] * nums[j]);
                ++j;
            }
            else if (j == n) {
                ans.push_back(nums[i] * nums[i]);
                --i;
            }
            else if (nums[i] * nums[i] < nums[j] * nums[j]) {
                ans.push_back(nums[i] * nums[i]);
                --i;
            }
            else {
                ans.push_back(nums[j] * nums[j]);
                ++j;
            }
        }

        return ans;
    }
};

209. 长度最小的子数组

题目链接

提交代码(方法-滑动窗口)
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result = nums.size() + 1;
        int left = 0;
        int curSum = 0;
        int subLen = 0;
        for(int right = 0; right < nums.size(); right++)
        {
            curSum += nums[right];
            while(curSum >= target)
            {
                subLen = right - left + 1;
                curSum -= nums[left++];
                result = subLen < result ? subLen : result;
            }       
        }
        return result == nums.size() + 1 ? 0 : result; 
    }
};
解答代码(方法1-暴力法)
class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int n = nums.size();
        if (n == 0) {
            return 0;
        }
        int ans = INT_MAX;
        for (int i = 0; i < n; i++) {
            int sum = 0;
            for (int j = i; j < n; j++) {
                sum += nums[j];
                if (sum >= s) {
                    ans = min(ans, j - i + 1);
                    break;
                }
            }
        }
        return ans == INT_MAX ? 0 : ans;
    }
};
解答代码(方法2-前缀和+二分查找)
class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int n = nums.size();
        if (n == 0) {
            return 0;
        }
        int ans = INT_MAX;
        vector<int> sums(n + 1, 0); 
        // 为了方便计算,令 size = n + 1 
        // sums[0] = 0 意味着前 0 个元素的前缀和为 0
        // sums[1] = A[0] 前 1 个元素的前缀和为 A[0]
        // 以此类推
        for (int i = 1; i <= n; i++) {
            sums[i] = sums[i - 1] + nums[i - 1];
        }
        for (int i = 1; i <= n; i++) {
            int target = s + sums[i - 1];
            auto bound = lower_bound(sums.begin(), sums.end(), target);
            if (bound != sums.end()) {
                ans = min(ans, static_cast<int>((bound - sums.begin()) - (i - 1)));
            }
        }
        return ans == INT_MAX ? 0 : ans;
    }
};
解答代码(方法3-滑动窗口)
class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int n = nums.size();
        if (n == 0) {
            return 0;
        }
        int ans = INT_MAX;
        int start = 0, end = 0;
        int sum = 0;
        while (end < n) {
            sum += nums[end];
            while (sum >= s) {
                ans = min(ans, end - start + 1);
                sum -= nums[start];
                start++;
            }
            end++;
        }
        return ans == INT_MAX ? 0 : ans;
    }
};

59. 螺旋矩阵II

题目链接

提交代码(方法)
class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> result(n, vector<int>(n, 0));
        if(n % 2 == 1)
            result[n / 2][n / 2] = n * n;
        int startx = 0;
        int starty = 0;
        int intervel = 1;
        int curCount = 1;
        int curX, curY;
        for(int i = 0; i < n / 2; i++)
        {
            curX = startx;
            curY = starty;
            for(; curY < n - intervel; curY++)
                result[curX][curY] = curCount++;
            for(; curX < n - intervel; curX++)
                result[curX][curY] = curCount++;
            for(; curY > starty; curY--)
                result[curX][curY] = curCount++;
            for(; curX > startx; curX--)
                result[curX][curY] = curCount++;
            intervel++;
            startx++;
            starty++;
        }
        return result;
    }
};
解答代码(方法)
class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        int t = 0;      // top
        int b = n-1;    // bottom
        int l = 0;      // left
        int r = n-1;    // right
        vector<vector<int>> ans(n,vector<int>(n));
        int k=1;
        while(k<=n*n){
            for(int i=l;i<=r;++i,++k) ans[t][i] = k;
            ++t;
            for(int i=t;i<=b;++i,++k) ans[i][r] = k;
            --r;
            for(int i=r;i>=l;--i,++k) ans[b][i] = k;
            --b;
            for(int i=b;i>=t;--i,++k) ans[i][l] = k;
            ++l;
        }
        return ans;
    }
};

总结

                     日期: 2023 年 3 月 16 日
              学习时长: 1 h 45 m
                     难度: ★ \bigstar ★ \bigstar ★ \bigstar ★ \bigstar
累计完成题目数量: 5
距离目标还有数量: 295
                      小结:

  1. 第一道题没什么说的,不过最开始我想的是先找到第一个大于等于零的数和最后以后小于零的数,然后由中间向两边迭代,但是这种方法的边界条件很难处理。
  2. 第二道题的滑动窗口可以实现O(n),但是答案还有一个nlogn,试着理解一下:它首先生成了一个数组存储前n个元素的和,那么外层循环还是n次,不过内层循环我需要在存有前n个元素和的数组内找到第一个大于等于当前目标加上前n-1个元素和的元素下标。
  3. lower_bound是查找大于等于目标的第一个元素下标
  4. 第三题做的比较水,边看答案边做的,主要是二维数组vector定义的时候没有初始化,所以不能引用,否则会出问题。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jeremy_dut

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值