B.D.S.代码随想录训练营day_2

声明:本账号博客完全是出于个人学习以及打卡目的,无意涉及任何利益。涉及引用的文章和代码都会尽量附上出处,以示尊重和感谢。

今日任务:

力扣:977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II

Part_1 力扣977.有序数组的平方

题目描述:

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

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/squares-of-a-sorted-array

个人最初解答:

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
       vector<int>re;
        for (int i = 0; i < nums.size(); ++i) {
            re.push_back(nums[i] * nums[i]);
        }
        sort(re.begin(), re.end());
        return re;
    }
};

        初步观察发现有相应函数可以直接调用,不过时间和空间复杂度有些高,力扣显示击败率大概都在20%左右。出于学习的目的,完成其他题目后,还是回来从算法角度做了一下,先附上卡哥的双指针。

卡哥解答:(代码引用自力扣评论,感谢卡哥)

class Solution {
public:
    vector<int> sortedSquares(vector<int>& A) {
        int k = A.size() - 1;
        vector<int> result(A.size(), 0);
        for (int i = 0, j = A.size() - 1; i <= j;) { // 注意这里要i <= j,因为最后要处理两个元素
            if (A[i] * A[i] < A[j] * A[j])  {
                result[k--] = A[j] * A[j];
                j--;
            }
            else {
                result[k--] = A[i] * A[i];
                i++;
            }
        }
        return result;
    }
};

        然后再简单描述一下个人思路。有些类似,同样是使用双指针,不过遇到的情况比较复杂。首先找出最小平方项的下标,并填为首项;然后从最小平方项出发,向两侧双指针(实际未必存在双侧),取小填入容器。由此发现,本题卡哥解答的妙处不仅仅是双指针,还有k--,即反向填入容器,这一步避免了很多弯路。由于个人技术尚不熟练,中间出发的双指针做法还有一些问题没有解决,所以暂时就不发在这里了,今天下午(哈哈,现在02:15,确实是今天下午)再认真检查一下,然后补发在评论区。

Part_2 力扣209.长度最小的子数组

题目描述:

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

 来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-size-subarray-sum

        由于本人之前稍微看过一些代码随想录,对滑动窗口有些印象,所以思路上没有很多需要额外补充,这里直接附上卡哥的原版滑动窗口。

卡哥解答:(代码引用自力扣评论,感谢卡哥)

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int result = INT32_MAX;
        int sum = 0; // 滑动窗口数值之和
        int i = 0; // 滑动窗口起始位置
        int subLength = 0; // 滑动窗口的长度
        for (int j = 0; j < nums.size(); j++) {
            sum += nums[j];
            // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
            while (sum >= s) {
                subLength = (j - i + 1); // 取子序列的长度
                result = result < subLength ? result : subLength;
                sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
            }
        }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
        return result == INT32_MAX ? 0 : result;
    }
};

        接下来,对卡哥这段代码简单补充一些注释,作为滑动窗口主体思路以外值得注意的细节。

result = result < k ? result : k;//记录k的最小值
 return result == INT32_MAX ? 0 : result;//若未sum >= target,则result = INT32_MAX

Part_3 力扣59.螺旋矩阵II

题目描述:

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

 来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/spiral-matrix-ii

本题难度标记为中等,原因可能在于初步观察其实际解答思路,似乎并没有太多可操作空间,大多可以想到逐层击破,若进一步探索,或许可以从数学的角度在通项上找到更好的规律。然而卡哥一句“左闭右开”可以使解答过程工整许多。

卡哥解答:(代码引用自力扣评论,感谢卡哥)

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
        int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
        int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
        int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
        int count = 1; // 用来给矩阵中每一个空格赋值
        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
        int i,j;
        while (loop --) {
            i = startx;
            j = starty;

            // 下面开始的四个for就是模拟转了一圈
            // 模拟填充上行从左到右(左闭右开)
            for (j = starty; j < n - offset; j++) {
                res[startx][j] = count++;
            }
            // 模拟填充右列从上到下(左闭右开)
            for (i = startx; i < n - offset; i++) {
                res[i][j] = count++;
            }
            // 模拟填充下行从右到左(左闭右开)
            for (; j > starty; j--) {
                res[i][j] = count++;
            }
            // 模拟填充左列从下到上(左闭右开)
            for (; i > startx; i--) {
                res[i][j] = count++;
            }

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

            // offset 控制每一圈里每一条边遍历的长度
            offset += 1;
        }

        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
        if (n % 2) {
            res[mid][mid] = count;
        }
        return res;
    }
};

    由于本人vector的应用并不熟练,因此前面初始化直接借用了卡哥的解答,不过后面尝试基于个人理解做出一些改动,绝对称不上是改进,权当个人理解。不难想到或者观察到卡哥解答中的startx、starty、offset有很多相同点,因此结合一些个人理解,直接合并为如下的z,相信细心的各位一定已经注意到其区别,即可解释性。同时,本人也尝试将卡哥的已经足够工整的左闭右开稍微调整,不过算法复杂度上并无变化,只是结合了一些个人对于涉及变量的理解。

个人解答:

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n, 0));
        int z = 0;
        int c = 1;
        int loop = n / 2;
        int mid = n / 2;
        while (z < loop) {
            int i = z;
            int j = z;
            for (; j < n - z - 1; j++) res[z][j] = c++;//上行
            for (; i < n - z - 1; i++) res[i][j] = c++;//右列
            for (; j > z; j--)  res[i][j] = c++;//下行
            for (; i > z; i--)  res[i][j] = c++;//左列
            z++;
        }
        if (n % 2 == 1) res[mid][mid] = n * n;
        return res;
    }
};

    今日感悟:

        由于之前看过一些代码随想录,这部分曾经对我感触颇深,因此时隔数月竟然还依稀有些印象,所以在解答思路的原创性方面并不侧重,不过希望能尽量独立复现一些主体思路,如双指针、滑动窗口等,在深化理解的同时也开始尝试诸如双指针的中间出发形式等,虽然复杂度上并不一定等同,何况改善。但对于代码随想录的学习绝对不只一轮,所以每一次的思考都值得肯定,并为之付出时间尝试。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
代码随想录算法训练是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

B.D.S.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值