Bootstrap

代码随想录算法训练营第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定义的时候没有初始化,所以不能引用,否则会出问题。
;