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

1.有序数组的平方

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

原题链接

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int l = 0, h = nums.size() - 1;
        vector<int> result(h + 1);
        int index = h;

        while (l <= h) {
            int low = nums[l] * nums[l];
            int high = nums[h] * nums[h];
            if (low > high) {
                result[index--] = low;
                l++;
            }
            else {
                result[index--] = high;
                h--;
            }
        }

        return result;
    }
};
  • 第一次错误解答,在原数组上进行操作, 破坏了相对顺序位置
class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        // 1.看到第一眼的想法,先平方再排序
        // 2. 可以使用双指针的方法,从两端的平方一直取最大值
        int l=0, h=nums.size() - 1;
        vector<int> result(h+1);
        while(l <= h){
            int low = nums[l] * nums[l];
            int high = nums[h] * nums[h];
			
			// 1。下面的操作会改变头部和尾部元素平方大小的排序相对顺序,因此出错
            if(low > high){			
                int temp = nums[h];
                nums[h] = low;
                nums[l] = t
            }
            else{
                nums[h] = high; 
            }
            h--;
        }
        return nums;
    }
};

2.长度最小的子数组(第一遍用双指针方法写错了,看了答案才做对)

原题链接

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

  • 注意点
    • 双指针法在这道题中慢指针和快指针在什么条件下分别前进
    • 计算距离
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int i=0, sum=0;
        // int min=nums.size();
        int min = INT32_MAX;
        bool flag = false;
        for(int j=0; j<nums.size(); j++){
        	sum += nums[j];		// 下面while循环已经将sum的值减小到小于target了
            // if(sum < target){
                //sum += nums[j];
            //}
            while(sum >= target){
                flag = true;
                int distance = j - i + 1;
                min = min < distance ? min : distance;
                /*
                if(distance < min){
                    min = distance;
                }*/
                // sum -= nums[i];
                 sum -= nums[i++];
            }
        }
        if(flag){
            return min;
        }

        return 0;
    }
};

2.1拓展题

  1. 水果成篮
    哈希与双指针的结合
    在这里插入图片描述
class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int n = fruits.size();
        unordered_map<int, int> cnt;

        int left = 0, ans = 0;
        for(int right = 0; right < n; ++right){
            ++cnt[fruits[right]];
            while(cnt.size() > 2){
                auto it = cnt.find(fruits[left]);
                --it->second;
                if(it->second == 0){
                    cnt.erase(it);
                }
                ++left;
            }
            ans = max(ans, right-left+1);
        }

        return ans;
    }
};

2. 最小覆盖子串

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。

class Solution {
public:
    unordered_map<char, int> ori, cnt;

    bool check(){
        for(auto &s : ori){
            if(cnt[s.first] < s.second){
                return false;
            }
        }

        return true;
    }

    string minWindow(string s, string t) {
        for(const auto & c : t){
            ++ori[c];
        }
        
        int l = 0, r = 0;
        int len = INT_MAX, ansL = -1;

        while(r < s.size()){
            if(ori.find(s[r]) != ori.end()){      // 当前遍历的字符 在t中
                ++cnt[s[r]];
            }

            while(check() && l<=r){             // 如果已经找到了满足条件的 子串
                if(r - l + 1 < len){
                    len = r - l + 1;
                    ansL = l;                   // 记录满足条件的子串的左边界
                }
                
                if(ori.find(s[l]) != ori.end()){
                    --cnt[s[l]];
                }
                ++l;
            }
            r++;
        }
        return ansL == -1 ? string() : s.substr(ansL, len);
    }
    
};

3.螺旋矩阵

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
在这里插入图片描述

  • 注意点:
    • 奇数大小的需要单独对矩阵中心点进行处理
    • 需要预判出一共需要循环多少圈 以及 每一圈的大小
class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        // 如果是n的平方,那么二维数组就是n行n列
        // 没循环完外面一圈内部就会剩下 n-2行列元素
        // 1. 先得知道一共得循环多少圈 a = n // 2 + (n%2)
        // 2. 计算当前圈有多大        b = n - a

        vector<vector<int>> result(n, vector<int>(n, 0));
        int x = 0, y = 0, num = 1;
        for (int i = 0; i < n / 2 + (n % 2); i++) {     // i代表了圈数
            for (int a = i; a < (n - i)-1; a++) { //第一行    // n-i代表了外圈大小
                result[i][a] = num++;
                x = i;
                y = a;
                cout << "[" << x << ", " << y << "]" << "-" << num << " ";
            }
            cout << endl;
            for (int b = i; b < (n - i)-1; b++) {
                result[b][n-i- 1] = num++;
                x = b;
                y = n - i - 1;
                cout << "[" << x << ", " << y << "]" << "-" << num << " ";
            }
            cout << endl;
            for (int c =(n-i)-1; c > i; c--) {
                result[n - i - 1][c] = num++;
                x = n - i - 1;
                y = c;
                cout << "[" << x << ", " << y << "]" << "-" << num << " ";

            }
            cout << endl;
            for (int d = (n - i - 1); d > i; d--) {
                result[d][i] = num++;
                x = d;
                y = i;
                cout << "[" << x << ", " << y << "]" << "-" << num << " ";
            }
            cout << endl;
        }

        if (n % 2 == 1) {
            int middle = n / 2;
            result[middle][middle] = n * n;
        }
        return result;

    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值