代码随想录刷题Day2 | 977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II

今日任务

977.有序数组的平方
209.长度最小的子数组
59.螺旋矩阵II

977. 有序数组的平方

方法一:二分找临界+双指针
(本题昨天有个数据是4,1,4,导致我无法直接用双指针来做,后面发现这个数据是莫名其妙多出来的)

主要思想: 从离0最近的两个数开始分别往左右方向遍历比较,将绝对值比较小的先放进res数组

time: O ( l o g n + n ) = O ( l o g n ) O(logn + n) = O(logn) O(logn+n)=O(logn)

记住一定要边写代码边检查,不然最后debug很耗时间!

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int mid, left = 0, right = nums.size() - 1, target = 0, len = nums.size();
        // 找的左边界
        while (left < right) {
            mid = (left + right) >> 1;
            if (nums[mid] >= target) right = mid;
            else left = mid + 1;
        }

        int pleft, pright;
        
        if (nums[left] == 0) pleft = left - 1, pright = left;
        else if (nums[left] < 0) pleft = left, pright = left + 1;
        else pleft = left - 1, pright = left;

        // cout << left << ' ' << right << endl;
        // cout << nums[pleft] << ' ' << nums[pright];
        // 人傻了,二分的条件写成 right < left了,num[mid]写成num[left]了

        vector<int> res;
        while (pleft >= 0 && pright <= len - 1) {
            if (abs(nums[pleft]) <= abs(nums[pright])) res.push_back(pow(nums[pleft--], 2));
            else res.push_back(pow(nums[pright++], 2));
        }
        while (pleft >= 0) res.push_back(pow(nums[pleft--], 2));
        while (pright <= len - 1) res.push_back(pow(nums[pright++], 2));
        
        return res;
    }
};

方法二:先算平方然后直接排序

暴力解法,主要复习下排序

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        for (int i = 0; i < nums.size(); ++i) {
            nums[i] = nums[i] * nums[i];
        }
        sort(nums.begin(), nums.end());
        return nums;
    }
};

方法三:先平方,然后使用双指针从两侧开始比较逆序对

class Solution {
public:
    // vector<int> sortedSquares(vector<int>& nums) {
    //     for (int i = 0; i < nums.size(); ++i) {
    //         nums[i] = nums[i] * nums[i];
    //     }
    //     // 完成后如果之前有负数,那么此时顺序是先递减后递增
    //     // 如果没有负数,那么是非严格递增
    //     // 两种情况都有较大数在外头
    //     // 所以用双指针从两头开始比较(逆序对)

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

    //     reverse(res.begin(), res.end());
    //     return res;
    // }
    // 简化版
    vector<int> sortedSquares(vector<int>& nums) {
        
        vector<int> res(nums.size());
        cout << res[0] << endl;
        int left = 0, right = nums.size() - 1, k = nums.size() - 1;

        while (left <= right) {
            if (nums[left] * nums[left] >= nums[right] * nums[right]) {
                res[k--] = nums[left] * nums[left];
                left++;
            }
            else {
                res[k--] = nums[right] * nums[right];
                right--;
            }
        }

        return res;
    }
};

209. 长度最小的子数组

滑动窗口
O ( n ) O(n) O(n)
主要思路

  • 当窗口内和小于target时,不停右移窗口的指针,直到其和大于窗口值
  • 当窗口不为空且内和大于target时,先更新最小值 m i n L e n = m i n ( m i n L e n , d q . s i z e ( ) ) minLen = min(minLen, dq.size()) minLen=min(minLen,dq.size()) ,再移动窗口左边的指针,重复这一步循环
  • 重复前两个循环直到右指针超出数组边界
class Solution {
public:
    // O(n), 使用deque,类似于双指针
    int minSubArrayLen(int target, vector<int>& nums) {
        deque<int> dq;
        int minLen = INT_MAX, sum = 0, i = 0;
        while (i < nums.size()) {
            // 先移动右边界
            while (sum < target && i < nums.size()) {
                dq.push_back(nums[i++]);
                sum += dq.back();
            }

            // 再移动左边界
            while ((dq.size()) && (sum >= target)) {
                minLen = minLen < dq.size() ? minLen : dq.size();
                sum -= dq.front();
                dq.pop_front();
            }
            cout << dq.size() << ' ' << i << endl;
        }
        
        return minLen == INT_MAX ? 0 : minLen;
    }
};

59. 螺旋矩阵 II

模拟即可
O ( n 2 ) O(n^2) O(n2)
分上下左右四个边界进行模拟即可
image-20230810220253181

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> Matrix(n, vector<int>(n));
        int num = 1, endNum = n * n, leftBound = 0, rightBound = n - 1, topBound = 0, bottomBound = n - 1;
        while (num <= endNum) {
            for (int i = leftBound; i <= rightBound; ++i) Matrix[topBound][i] = num++;
            topBound++;
            for (int i = topBound; i <= bottomBound; ++i) Matrix[i][rightBound] = num++;
            rightBound--;
            for (int i = rightBound; i >= leftBound; --i) Matrix[bottomBound][i] = num++;
            bottomBound--;
            for (int i = bottomBound; i >= topBound; --i) Matrix[i][leftBound] = num++;
            leftBound++;
        }
        return Matrix;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值