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

Leetcode 977. 有序数组的平方

初见想法:因为数组存在负数,所以想设置左右两个指针,不断比较平方,直到左指针>0。或者直接先平方,然后直接sort ??

直接平方,然后用自带函数排序,时间复杂度为O(nlogn):

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

最简单的方法,不是很好看

双指针法,重点是找到负数与非负数的分界线,然后就和归并排序的思想差不多。

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {

        int size = nums.size();
        int negative = -1;
        // 这里的前提是数组是非递减顺序
        for (int i = 0; i < size; i++)
        {
            if (nums[i] < 0) negative = i;
            else break;
        }

        vector<int> ans;
        int i = negative, j = negative+1;
        while (i >= 0 || j < size)
        {   
            // 先判断i和j,防止越界
            if (i < 0)
            {
                ans.push_back(nums[j]*nums[j]);
                j++;
            }
            else if (j == size)
            {
                ans.push_back(nums[i]*nums[i]);
                i--;
            }
            else if (-nums[i] < nums[j])
            {
                ans.push_back(nums[i]*nums[i]);
                i--;
            }
            else
            {
                ans.push_back(nums[j]*nums[j]);
                j++;
            } 
        }
        return ans;
    }
};

时间复杂度为O(n), 需要辅助数组,与归并排序类似。

最后一种双指针法,倒排,需要确定新数组的长度。

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {

        int m = nums.size();
        vector<int> ans(m);

        for (int i = 0, j = m-1, pos = m-1; i <= j; pos--)
        {
            if (nums[i]*nums[i] > nums[j]*nums[j])
            {
                ans[pos] = nums[i]*nums[i];
                i++;
            }
            else
            {
                ans[pos] = nums[j]*nums[j];
                j--;
            }
        }

        return ans;
    }

};

双指针法,最巧妙的办法,左右两个指针,左指针往右,右指针往左,当两个指针相遇时即遍历完整个数组。新数组从后往前排。时间复杂度为o(n),空间复杂度为o(n)

总结:两个指针快速遍历数组,排序不仅可以正着排,也可以倒着排。

Leetcode 209. 长度最小的子数组

初见想法:想到了滑动窗口的方法,但是怎么表示滑动窗口呢,用两个指针吗?

要思考如何移动窗口的初始位置和终止位置。

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        
        int result = INT32_MAX;             
        int i = 0;
        int sum = 0;
        
        int size = nums.size();
        for (int j = 0; j < size; j++)
        {
            sum += nums[j];

            while (sum >= target)
            {
                int sublength = j - i + 1;
                result = sublength < result ? sublength:result;
                sum -= nums[i++];
            }
        }

        return result == INT32_MAX ? 0:result;
    }
};
  1. 使用两个指针表示滑动窗口

  1. for循环表示滑动窗口的终止条件

  1. 最大值可以用INT32_MAX表示

Leetcode 59.螺旋矩阵II

初见想法:循环不断的填入数据

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        int left = 0, right = n-1, top = 0, bottom = n-1;
        int count = 1, target = n*n;

        vector<vector<int>> ans(n, vector<int>(n));

        while (count <= target)
        {
            for (int i = left; i <= right; i++) ans[top][i] = count++;
            top++;
            for (int i = top; i <= bottom; i++) ans[i][right] = count++;
            right--;
            for (int i = right; i >= left; i--) ans[bottom][i] = count++;
            bottom--;
            for(int i = bottom; i >= top; i--) ans[i][left] = count++;
            left++;
        }

        return ans;
    }
};

总结:模拟法,不考察算法,考察边界处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值