刷题记录Day2-数组(有序数组的平方、长度最小的子数组、螺旋矩阵)

刷题记录Day2-数组(有序数组的平方、长度最小的子数组、螺旋矩阵)

简单记录



前言

题目来源:leetcode
刷题顺序:代码随想录
刷题工具:VSCode+leetcode插件
补充:延毕时间充裕,会结合LeetCode 101: A LeetCode Grinding Guide (C++ Version)相似题目一起做。


一、有序数组的平方

还是双指针类型的题目。

1. 977有序数组的平方

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

示例:

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

代码:

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int l =0, r = nums.size()-1, n = nums.size();
        vector<int> res(nums.size(),0);
        while (l <= r){
            if (abs(nums[r]) >= abs(nums[l])){
                res[--n] = pow(nums[r--],2);
            }
            else{
                res[--n] = pow(nums[l++],2);
            }
        }
        return res;
    }
};

二、长度最小的子数组

1. 209长度最小的子数组

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

示例:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

代码:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int l =0, r = 0, sum =0;
        int min_size = nums.size()+1;
        for (r=0; r < nums.size(); ++r){
            sum+= nums[r];
            while (sum >= target){
                min_size = (r-l+1) < min_size? (r-l+1) : min_size;
                sum-=nums[l++];
            }
        }
        return min_size <(nums.size()+1)?min_size:0;
    }
};

只用一个for循环,那么这个循环的索引,一定是表示滑动窗口的终止位置。

2. 904水果成篮

题目:
你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。
你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。

示例:

输入:fruits = [0,1,2,2]
输出:3
解释:可以采摘 [1,2,2] 这三棵树。
如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。

代码(题解方法):

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        unordered_map <int, int> cla;
        int l = 0, r = 0, max_size = 0;
        for (r = 0; r < fruits.size(); ++r){
            ++cla[fruits[r]];
            while (cla.size() >2){
                if(--cla[fruits[l]] == 0){
                    cla.erase(fruits[l]);
                }
                ++l;
            }
            max_size = max(r-l+1,max_size);

        }
        return max_size;
    }
};

该方法采用哈希表+滑动窗口。

代码(讨论里的方法):

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int l = 0, r = 0, max_size = 0;
        int lbasket = fruits[l], rbasket = fruits[r]; //篮子一号和二号
        while ( r < fruits.size()){
            if (fruits[r] == lbasket || fruits[r] == rbasket){//属于篮子某个种类
                max_size = max(max_size, r-l+1); //更新结果,每次取一个数就更新一下
                ++r;
            }
            //如果遇到第三种,把慢指针移动到快指针前一步,该步的水果种类必然不同于快指针,此时慢指针慢慢回退齐所有的连续同类。
            else{
                rbasket = fruits[r];
                l= r-1;
                lbasket = fruits[l];  //更新第一个篮子
                while (l >= 1 && fruits[l-1] == lbasket){
                    --l;
                }
                max_size = max(max_size, r-l+1);

            } 
        }
        return max_size;
    }
};

只用了滑动窗口,太厉害了,我自己的思路也是这样,但就是写不出来。

3. 76最小覆盖子串

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

示例:

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A''B''C'

代码:

class Solution {
public:
    string minWindow(string s, string t) {
        vector<int> ch(128,0);
        vector<bool> ap(128,false);
        for (size_t i = 0; i != t.size(); ++i){
            ap[t[i]] = true;
            ++ch[t[i]];
        }
        
        //滑动窗口,一左一右两个指针
        int l = 0, cnt = 0 , min_l = 0, min_size = s.size()+1;
        for (size_t r = 0; r != s.size(); ++r){
            if (ap[s[r]]){
                if (--ch[s[r]] >= 0){
                    ++cnt;
                }
            }
            while (cnt == t.size()){
                if (r-l+1 < min_size){
                    min_size = r-l+1;
                    min_l = l;
                }
                if (ap[s[l]] && ++ch[s[l]] > 0){
                    --cnt;
                }
                ++l;
            }
        }
        return min_size>s.size()?"":s.substr(min_l,min_size);
    }
};

这道题在leetcode101做过,这次换了个while的写法结果没写出来,太糟糕了,为了图代码简洁写成ap[s[r++]],没注意到这样的话后面所有的r都加了一位。可惜可惜。

三、螺旋矩阵

1. 59螺旋矩阵II

好讨厌做这种题目!!

题目:
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

示例:

示例 1:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

图片来源leetcode-59题
代码:

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res (n, vector<int> (n,0));
        int i =0, j = 0, num =2;
        res[0][0] =1;
        while(num<= n*n){
            while (j < n-1 && res[i][j+1] == 0){
                res[i][++j] = num++;
            }
            while (i < n-1 && res[i+1][j] == 0 ){
                res[++i][j] = num++;
            }
            while (j > 0 && res[i][j-1] == 0){
                res[i][--j] = num++;
            }
            while (i > 0 && res[i-1][j] == 0){
                res[--i][j] = num++;
            }
        }
        return res;
    }
};

2. 54螺旋矩阵

太恶心了,做过类似的了,然后对着答案做都做不对!!!

题目:
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

示例:
图片来源于leetcode-54

输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]

代码:

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        int raws = matrix.size(); //行
        int cols =matrix[0].size(); //列
        int n = min(raws,cols)/2;
        vector<int> res;
        int i =0, j = 0, offset =1;
        int startx =0, starty =0;
        while (n--){
            for (j = starty; j < cols-offset; ++j){
                res.push_back(matrix[startx][j]);
            }
            for (i = startx; i < raws-offset; ++i){
                res.push_back(matrix[i][j]);
            }
            for (; j > starty; --j){
                res.push_back(matrix[i][j]);
            }
            for (; i >startx; --i){
                res.push_back(matrix[i][j]);
            }
            ++startx;
            ++starty;
            ++offset;
        }
        if(min(raws,cols)%2 == 1){ //小的那个值如果是奇数,就要额外输出一行或一列
            if (raws > cols){
                for (i = startx; i< raws-offset+1; ++i){
                    res.push_back(matrix[i][starty]);
                }
            }
            if (cols > raws){
                for (j = starty; j< cols-offset+1; ++j){
                    res.push_back(matrix[startx][j]);
                }
            }
            if (raws == cols && raws%2 ==1){
                res.push_back(matrix[startx][starty]);
            }   
        }
        return res;

    }
};

牛逼,功夫不负有心人,看了讨论区后想到一种方法。给每一个要输出的值立一个flag,初始化为false。在螺旋循环过程中,如果是遇到false,就输出他并将它的flag改为1,否则就不输出了。(虽然我发现空间时间复杂度都很垃圾,但好歹是自己好理解的方法。)

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        int raws = matrix.size(); //行
        int cols =matrix[0].size(); //列
        int n = raws*cols;
        int i =0, j= 0;
        vector<int> res;
        vector<vector<bool>> flag (raws,vector<bool>(cols,false));
        res.push_back(matrix[0][0]);
        flag[0][0] = true;
        while (n-1 > 0){
            while (j< cols-1 && !flag[i][j+1]){
                flag[i][j+1] =true;
                res.push_back(matrix[i][++j]);
                --n;
            }
            while (i< raws-1 && !flag[i+1][j]){
                flag[i+1][j] =true;
                res.push_back(matrix[++i][j]);
                --n;
            }
            while (j> 0 && !flag[i][j-1]){
                flag[i][j-1] =true;
                res.push_back(matrix[i][--j]);
                --n;
            }
            while (i> 0 && !flag[i-1][j]){
                flag[i-1][j] =true;
                res.push_back(matrix[--i][j]);
                --n;
            }
        }
        return res;

    }
};

总结

今天做的特别慢感觉,处理边界情况真的太烦了,痛苦。还有两道扩展题目还在想。
我要是面到螺旋矩阵我螺旋放弃。(又不想放弃了)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值