算法Day2——977.有序数组的平方& 209. 长度最小的子数组

leetcode之977.有序数组的平方

一、题目要求

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

示例 1:

  • 输入:nums = [-4,-1,0,3,10]
  • 输出:[0,1,9,16,100]
  • 解释:平方后,数组变为 [16,1,0,9,100],排序后,数组变为 [0,1,9,16,100]

示例 2:

  • 输入:nums = [-7,-3,2,3,11]
  • 输出:[4,9,9,49,121]

二、解题思路

乍一看,平方完了不就行了?原来是还有负数,负数平方完了就不是一个递增序列了,所以要处理负数的问题,简单的想法就是暴力的平方,然后排序。这样的时间复杂度就是O(nlogn),不符合本题要求的O(n)。

O(n)提示1、一个for循环,然后比较判断后,重组就可以了。

三、代码实现

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int left = 0;
        int right = nums.size()-1;
        while (left < right){
            if(nums[left]* nums[left] < nums[right]*nums[right]){
                    nums[right] = nums[right]*nums[right];
                    right--;
            }else{
            nums[right] = nums[left]* nums[left];
            left++;
            }
        }
        return nums;
    }
};

自己写的代码,发现不太对劲,编译一下[-4,-1,1,256,100],问题1、没有用另一个数组保存,直接使用了原数组,导致数据混乱。2、新数组的指针也需要重新定义。 优化一下:

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int left = 0;
        int right = nums.size()-1;
        int flag = nums.size()-1;
        vector<int> result(nums.size(), 0);
        while (left <= right){
            if(nums[left]* nums[left] < nums[right]*nums[right]){
                    result[flag] = nums[right]*nums[right];
                    flag--;
                    right--;
            }else{
            result[flag] = nums[left]* nums[left];
            flag--;
            left++;
            }
        }
        return result;
    }
};

leetcode之209.长度最小的子数组

一、题目要求

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。

二、解题思路

1.暴力解法,两个for循环,过程略,一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环 完成了一个不断搜索区间的过程。

2.滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果

三、代码实现

看了示例的错误实现:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
           int flag = 0;
           vector<int> result(2, 0);
           for(int i = 0; i < nums.size()-1; i++){
                   if(nums[i]+nums[i+1]>target){
                        flag++;
                   }
           }
           return flag;
    }
};

自序列的长度是可以变化的,所以不能写死,这个长度只是2了。。傻了。

自己敲一遍:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result = INT32_MAX;
        int slide_sum = 0;
        int len = 0;
        int i = 0; // 这个不要在里面初始化
        for(int j = 0; j < nums.size(); j++){
               slide_sum += nums[j];
               while (slide_sum >=  target){
               len = j - i + 1;
               result = result < len ? result: len;
               slide_sum -= nums[i++];  // 这步很关键,i代替了for循环,表示子序列的初始位置
               }
        }
        return result == INT32_MAX ? 0 : result;
    }
};

leetcode之59.螺旋矩阵II

一、题目要求

给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。

二、解题思路

主要是循环的过程中对于边界的控制,需要记录的是圈数,X轴和y轴某个具体的数值,中间数值的控制。

三、代码实现

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
        int start_id = 0 , end_id = 0;
        int loop =n / 2;
        int mid_num = n /2; //中间的数
        int count = 1 ; // 记录走的步数
        int i,j;
        int flag = 1;
    while(loop--){
        i = start_id;
        j = end_id;

        // 模拟填充上行从左到右(左闭右开)
        for( j= start_id ; j < n - flag; j++){
            res[start_id][j] = count++;
        }
        for( i =start_id; i < n - flag; i++ ){
            res[i][j] = count++;
        }
       // 模拟填充下行从右到左(左闭右开)
        for (; j > start_id; j--) {
            res[i][j] = count++;
        }
        // 模拟填充左列从下到上(左闭右开)
        for (; i > start_id; i--) {
            res[i][j] = count++;
        }

        // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
        start_id++;
        end_id++;

        // offset 控制每一圈里每一条边遍历的长度
        flag += 1;
    }
    // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
    if (n % 2) {
        res[mid_num][mid_num] = count;
    }
    return res;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值