LeetCode 977有序数组的平方 209长度最小的子数组 904水果成篮 76最小覆盖子串 59 螺旋矩阵II | 代码随想录25期训练营day2

如果觉得写的还行的话辛苦点赞!收藏!关注!共同学习呀!

LeetCode 977 有序数组的平方 2023.10.26

  • 题目链接
  • 代码随想录讲解[链接]
    LeetCode 977有序数组的平方 209长度最小的子数组 904水果成篮 76最小覆盖子串 59 螺旋矩阵II | 代码随想录25期训练营day2_第1张图片
  • 题意:已知一个整数数组,其中元素可能有正有负有0有重复,按非递增顺序排序,要求得出数组内每个元素的平方,平方后的元素按非递减顺序成为一个数组输出
  • 输入样例:[-5, -3, -2, -2, 0, 1, 2, 3, 3, 5]
  • 方法1:暴力求解,求出每个元素的平方后存入新数组,再将新数组排序后输出
  • 方法2:双指针法,因为每个元素绝对值越大,平方越大!绝对值大的在数组两边,那么定义两个索引left,right分别从两侧遍历,依次记录绝对值更大值的平方存入新数组,当left>right时说明遍历完成,得到答案!
vector<int> sortedSquares(vector<int>& nums) {
    //记录nums中元素个数size
    int size = nums.size();
    //创建元素平方后的存储数组,即答案数组
    vector<int> temp(size);
   	//平方数组的元素个数=nums数组中元素个数,用size_t表示下次放入元素位置的索引
	//因为要按非递减顺序,那么首先进入的平方值最大,从后面依次放入,最后一个索引为size-1
    int size_t = size -1;
    //开始遍历,左右两个指针索引分别为0和size-1,当i>j时代表计算完成得到答案
    for (int i = 0, j = size-1; i <= j;)
    {
        //当nums数组右侧绝对值更大或相等时,将其平方值填入平方数组,右侧索引左移j--;平方数组索引size_t--
        //abs()求绝对值,pow(a, n)求a的n次方
    	if (abs(nums[i]) <= abs(nums[j]))
    	{
    		temp[size_t] = pow(nums[j], 2);
    		size_t--;
    		j--;
    	}
        //当nums数组左侧绝对值更大时,将其平方值填入平方数组,左侧索引右移i++;平方数组索引size_t--
    	else
    	{
            temp[size_t] = pow(nums[i], 2);
            size_t--;
            i++;
    	}
    }
    //返回答案(平方数组)
    return temp;
}

LeetCode 209 长度最小的子数组 2023.10.26

  • 题目链接
  • 代码随想录讲解[链接]
    LeetCode 977有序数组的平方 209长度最小的子数组 904水果成篮 76最小覆盖子串 59 螺旋矩阵II | 代码随想录25期训练营day2_第2张图片
  • 题意:输入一个有n个正整数的无顺序数组,一个目标值target,查找该数组中元素和大于等于目标值的最短子数组,返回的是该最短子数组的长度,如果没找到则返回0
  • 方法1:暴力求解,两层for()循环遍历,计算从每个元素开始的满足条件的最短子数组的长度,最后输出一个最短长度
  • 方法2:滑动窗口,窗口有左、右边界,右边界负责增大窗口,加入新元素;左边界负责减小窗口,去掉窗口左边界元素;当窗口内元素和小于目标值时,右边界增加;当窗口内元素和满足大于等于目标值时,更新最短长度,然后减小左边界再次判断元素和与目标值关系
int minSubArrayLen(int target, vector<int>& nums) {
    //定义最短长度变量并初始化其为数组长度+1
    int min = nums.size()+1;
    //定义窗口内元素和值,初始化为0
    int sum = 0;
    //开始遍历,最初窗口左右边界都为0
    for(int i = 0, j = 0; i < nums.size(); i++)
    {
        //计算窗口内元素和,没达到要求时窗口右移,元素和增加
        sum += nums[i];
        //当元素和大于等于目标值时,循环判断左边界减小是否还满足条件
        while(sum >= target)
        {
            //更新最短长度
            if(min >= i-j+1)
                min = i-j+1;
            //减小窗口,左边界右移,更新窗口内
            sum -= nums[j++]; 
        }
    }
    //如果仍是初始值说明没找到返回0,否则返回最短长度值
    return min == nums.size()+1 ? 0 : min;
}

LeetCode 904 水果成篮 2023.10.25

  • LeetCode 904 水果成篮[题目链接]
    LeetCode 977有序数组的平方 209长度最小的子数组 904水果成篮 76最小覆盖子串 59 螺旋矩阵II | 代码随想录25期训练营day2_第3张图片

  • 题意:种植一排未知果实类型的果树,用一个数组表示每棵树上的果实类型,现有两个筐用于分别装两种类型的果实,问:从一排树中任意一棵开始,保证两个筐内的果实同种类型,最多能从几棵树上摘到果实

  • 方法1:暴力搜索,两个for()循环,记录从每棵树开始摘,最多能摘几棵树,最终得出最大值;时间复杂度为O(n^2)

  • 方法2:滑动窗口

    • 首先用两个全局变量记录两个篮子里所装的果实类型,并分别标记为先采筐和后采筐
    • 开始遍历,当采摘树果实类型与两个筐内任意一种相同时,增加当前可采摘树的棵树并更新最大可摘棵树,继续遍历;当采摘树果实类型不与两个筐内果实类型相同时,更新先采筐类型为当前采摘树的上一棵树的类型,后采筐类型为当前采摘树类型,并开始反向遍历,记录这两种类型果实的反向最大可采摘树,最后再正向遍历,继续更新
    • 小心!当采摘了的棵树变化时,必须判断是否需要更新最大可采摘棵树
int totalFruit(vector<int>& fruits) {
    int pose = 0;
    int x = fruits[0], y = x;
    int max = 0, num = 0;
    for(int i = 0; i < fruits.size(); i++)
    {
        if(fruits[i] != x && fruits[i] != y)
        {
            x = fruits[i-1];
            y = fruits[i];
            pose = i - 1;
            while (pose >= 0)
            {
                if(fruits[pose] == x || fruits[pose] == y)
                    pose--;
                else
                    break;
            }
            num = i - pose;
            if(num >= max)
                max = num;
            continue;
        }
        num++;
        if(num >= max)
            max = num;
    }
    return max;
}

LeetCode 76 最小覆盖子串 2023.10.25

  • 题目链接

  • labuladong讲解[链接]
    LeetCode 977有序数组的平方 209长度最小的子数组 904水果成篮 76最小覆盖子串 59 螺旋矩阵II | 代码随想录25期训练营day2_第4张图片

  • 题意:给定两个字符串s, t, 将在字符串s中查找包含字符串t中所有字符的最小覆盖子串,注意不需要按t中字符顺序,而且t中重复字符,要寻找的子字符串中该字符数量大于等于t中该字符数量

string minWindow(string s, string t) {
    //建立无序图存储所查字符串t以及当前窗口下子串字符及其个数
    unordered_map<char, int> need, window;
    //记录所查字符串t中字符及其个数
    for(char c : t) need[c]++;

    //窗口的左右界限,以及找到了的标志
    int left = 0, right = 0;
    int valid = 0;

    //用于记录最小覆盖子串的起始索引及长度,初始值设为了s串长度+1
    int start = 0, len = s.length()+1;
    //开始查找,将s中所有字符遍历
    while (right < s.length())
    {
        //用于记录当前字符
        char c = s[right];
        //窗口右移扩大范围
        right++;
        //开始判断t中是否需要
        if(need.count(c))
        {
            //如果需要,窗口中该字符的数量加一,无论是否超过了所要搜索的t中该字符的数量
            window[c]++;
            //滑动窗口中当该字符的个数等于所要查找的该字符数量时,已找到字符种类数+1
            if(window[c] == need[c])
                valid++;
        }
        //是否找到了覆盖子串的标志,找到字符种类数==被找字符串t中字符种类数
        while (valid == need.size())
        {
            //判断当前窗口大小是否比已存储最小子串长度小
            if(right - left < len) 
            {
                //记录最小子串开始索引及长度
                start = left;
                len = right - left;
            }
            //将缩小窗口,记录窗口最左侧字符
            char d = s[left];
            //窗口缩小,左侧右移
            left++;
            //判断要去掉的字符是否有被需要
            if(need.count(d))
            {
                //当该字符“刚需”时,去掉该字符导致完成查到字符种类数-1
                if(window[d] == need[d])
                    valid--;
                //窗口减小,减小窗口中当前字符的个数
                window[d]--;
            }
        }
    }
    //返回答案,如果没有找到(仍等于默认值时),返回“”,否则返回最小覆盖子串
    return len == s.length()+1 ? "" : s.substr(start, len);
}

LeetCode 59 螺旋矩阵II 2023.10.26

  • 题目链接
  • 代码随想录讲解[链接]
    LeetCode 977有序数组的平方 209长度最小的子数组 904水果成篮 76最小覆盖子串 59 螺旋矩阵II | 代码随想录25期训练营day2_第5张图片
  • 题意:输入一个正整数n,构建一个n x n的数组,顺时针循环走圈,到达的每格赋值,从1开始,每次+1,最后一格为n x n
  • 方法:确定赋值位置行坐标列坐标,具有4个规律,分别为向右赋值,向下赋值,向左赋值,向上赋值,依次循环,为保证赋值(边界)规则统一,选择左闭右开,每条规律只给边首赋值,边尾留给下个规律赋值,保证不会乱以及重复
  • 创建返回的二维数组时必须初始化大小vector> result(n, vector(n, 0));,否则在使用双[]访问元素可时编译不通过
vector<vector<int>> generateMatrix(int n) {
    //创建返回的二维数组,需要初始化大小,这里还初始化为了0
    vector<vector<int>> result(n, vector<int>(n, 0));
    //每条边的初始值
    int startx = 0, starty = 0;
    //二维数组的行索引i与列索引j
    int i = 0, j = 0;
    //需要绕几圈,n为偶数时,绕n/2圈后所有元素都完成赋值;
    //n为奇数时,绕n/2圈后留下最中间的一个数未赋值,最后赋值为n x n
    int loop = n/2;
    //每绕一圈后,下一圈要赋值的每条边元素个数减少,通过其控制每条表的尾
    int cut = 1;
    //要赋的值参数,第一个为1,然后递增
    int value = 1;
    //开始绕圈
    while(loop--)
    {
        //向右,行坐标不变,列坐标递增,右边界为(n-cut不赋值,留给向下首位置赋值),
        //初始位置分别为(0,0)(1,1)(2,2)...左上角
        for(j = starty; j < n - cut; j++)
        {
            result[startx][j] = value++;
        }
        //向下,列坐标不变,行坐标递增,下边界为(n-cut不赋值,留给向左首位置赋值),
        //初始位置分别为(0,n-1)(1,n-2)(2,n-3)...右上角
        for(i = startx; i < n - cut; i++)
        {
            result[i][j] = value++;
        }
        //向左,行坐标不变,列坐标递减,左边界为(cut-1不赋值,留给向上首位置赋值),
        //初始位置分别为(n-1,n-1)(n-2,n-2)(n-3,n-3)...右下角
        for(; j > cut - 1; j--)
        {
            result[i][j] = value++;
        }
        //向上,列坐标不变,行坐标递减,上边界为(cut-1不赋值,留给向右首位置赋值),
        //初始位置分别为(n-1,0)(n-2,1)(n-3,2)...左下角
        for(;i > cut - 1; i--)
        {
            result[i][j] = value++;
        }
        //每一圈的初始位置变动,(0,0)(1,1)(2,2)...
        startx++;
        starty++;
        //每一圈经过的边长减小,用cut控制
        cut++;
    }
    //n为奇数时,绕n/2圈后留下最中间的一个数未赋值,最后赋值为n x n
    if(n%2 == 1)
        result[n/2][n/2] = value;
    return result;
}

如果觉得写的还行的话辛苦点赞!收藏!关注!共同学习呀!

你可能感兴趣的:(LeetCode刷题,代码随想录训练营,leetcode,算法,数据结构)