前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >算法小白如何高效刷LeetCode?

算法小白如何高效刷LeetCode?

作者头像
果冻虾仁
发布2021-12-08 13:27:10
1.4K0
发布2021-12-08 13:27:10
举报
文章被收录于专栏:后台公论

心理建设篇

在讲述具体的方法之前,先要明白一件事。凡事都分『道』与『术』。本问题下面大部分回答介绍的都是『术』。而对于刷LeetCode这件事,无论你看到多少高明的的方法,如果你不能持之以恒,都没有用。所有在刷LeetCode这件事上,他的『道』就是:如何能持之以恒的保持刷题热情。我认为『道』更重要。我先谈一下这部分。

寻找标尺,让进步可衡量

为什么王者荣耀有段位,有青铜、白银、黄金。以我个人的经验来看,这些都是刺激你持续玩游戏的游戏机制。通过段位,彰显个人的实力,没错,装逼是人类进步的一大动力。同时也让进步可以衡量。刷LeetCode也是同样,一般刚开始我们会关注解决了多少道题。更进一步,我们需要关心自己的排名。LeetCode也有排名机制。每刷一道题,就前进一点点。可以每周给自己做一个记录,记一下自己的排名。让自己重视排名。逐渐的自己就会把积极性调动起来,想让自己的排名越来越高,就是打排位一样。

除了排名,你还可以每周记录一下通过率。

寻找小惊喜,给自己正反馈

坚持做每日一题,LeetCode每天都有一道题,完成后,你的打卡日历就会勾上一个圈。

如果打满一个月就会获得一个月度徽章。另外LeetCode有很多“学习计划”,每个学习计划完成后也会有一个徽章。

我有段时间就喜欢收集徽章,为了收集这些小玩意,会刺激自己持续解题。其实和游戏里面也差不多。学会游戏化学习。

不要死磕,学会放弃

开始刷LeetCode感到吃力是正常的。我这里说的学会放弃,不是说放弃刷力扣,而是说碰到自己无法解决的题目,不要死磕。赶紧看一下题解去学习,这没有什么丢人的。每个人都是从这个阶段过来的。就比如小学生无法做出高中生的题目,并不是因为小学生笨,而是因为中间有很多知识,小学生没学过。对于算法而言,自然也是如此。靠自己死磕,是很难想到很多前辈科学家们总结出来的算法。这时候去看题解学习也不为过。

如果遇到特别难的题,看题解也不理解。也不用纠结。就隔着它。可以把题号记下来。过段时间再回顾。

好记性不如烂笔头

我是笔记强迫症患者……我现在刷LeetCode,每道做过的题,我都会记到Notion里。打上几个标签,方便回顾。

记忆是有遗忘曲线的,不能因为你现在能做出一道题,就认为自己能永远做出来。小学时,老师就教导我们:

好记性不如烂笔头

讲完『道』,我也谈一下我的『术』。我这里不对具体的算法和数据结构题型做解析了,我主要给你指路。

我伸手给你指路,希望你看见的是路,而不是我的手

刷题顺序篇

当然我不建议从头按顺序刷,我分为“正排”刷题和“倒排”刷题,两种策略。

所谓“正排刷题”可以刷LeetCode上面的题单。

我个人建议从《剑指Offer》开始刷。《剑指Offer》现有出了两册,在LeetCode上都有题单。建议从《剑指Offer》刷起,碰到不会的,可以看书中的讲解。

根据书来刷题,当你刷完一本书后,常见的题目类型几乎都覆盖到了。当然同一种类型的题目数不胜数,重要是培养一下各种题型大概的思路。这属于“正排”刷题。

“倒排”刷题,是打破常规,不根据题目类型或按照某种顺序来做题。玩的就是措手不及。比如坚持做每日一题。坚持一个月你就会见到各种各样的题型,有的甚至很刁钻。方便查漏补缺。另外如果有信心的话,可以参加一下周赛,进一步给自己惊喜。

网站/APP使用篇

自定义测试用例

不要着急提交代码。多用测试用例自测。如果是提交之后发现某个case不过,调试的时候一定要在测试用例这里调试。

不要用重复提交代码的方式调试。每次提交代码都会跑N多个case,时间慢。另外就是会降低你在LeetCode上的“通过率”

高效安排刷题时间

如果你是学生,那么恭喜你有一大把的时间用来刷题。但是如果你是已工作人士,则需要高效利用时间了。由于我经常做每日一题,而每日一题,是零点更新。有时候躺在床上没睡,就用力扣APP打开看一眼题目,如果题目不难,就直接用APP刷了。另外你也可以利用上下班通勤的时间、出去玩乘坐地铁、公交的时间来用手机看看题解,或者直接用手机刷。比如我坐长途车从家里回北京的路上就用手机刷过题。

手机刷题,其实官方APP,有很多编程语言中的特殊符号的候选功能,可以加快不少手机输入的速度。

另外你可以给你的输入法用自定义,加入一些常用的代码,进一步提高手机输入的效率。

Trick篇

修改函数参数

leetcode的参数名,有时候很长,你可以改名字,减少输入的字符数。当然正常在网站上刷题有补全功能。但是改一下名字,还是简化不少。另外就是有两个例外情况是没有补全的:

  1. 手机刷题(力扣手机APP可以刷题,但是没有补全功能)
  2. 参加周赛(周赛IDE,无自动补全功能)

调用待补全函数自身

如果函数的参数是等价的,但是你根据某种策略,把他们分出来差别。但是你不确定哪个参数是满足的。比如这道:

415. 字符串相加

https://leetcode-cn.com/problems/add-strings

官方给出的代码是这样:

代码语言:javascript
复制
class Solution {
public:
    string addStrings(string num1, string num2) {

    }
};

num1和num2在题目中含义是等价的。但是我们希望以长度长的那个num作为base,来叠加长度短的那个num。这样可以方便处理。你可以直接去判断长度,然后再搞两个变量出来。比如:

代码语言:javascript
复制
auto& base = num1.size() > num2.size() ? num1: num2;
auto& delta = &base == &num1 ? num2 : num1;

然后让base再去加delta。。但其实没必要这么麻烦,直接这样:

代码语言:javascript
复制
class Solution {
public:
    string addStrings(string num1, string num2) {
        if (num1.size() < num2.size()) {
            return addStrings(num2, num1); // 调用自身
        }
        reverse(num1.begin(), num1.end());
        reverse(num2.begin(), num2.end());
        // num1长度 肯定大于等于num2
        stringstream ss;
        int c = 0;
        for (int i = 0; i < num1.size(); ++i) {
            int x = num1[i] - '0';
            int y = i < num2.size() ? num2[i] - '0' : 0;
            int n = x + y + c;
            int d = n%10;
            ss<<d;
            c = n/10; 
        }
        if (c) {
            ss << c;
        }
        string s = ss.str();
        reverse(s.begin(), s.end());
        return s;
    }
};

给解题函数增加默认值

每道题,LeetCode都会给出一个待补全的函数,这个函数,你是可以增加默认值的。

对于某些递归的解法,可以少定义一个函数.

官方库提升刷题效率(C++)

因为我是C++程序员所以下面就只介绍C++了。

记住一定要学好STL!

swap替代手写交换

不要在自己写三行式去写交换了。直接用swap。

针对链表的Node也使用哦。比如:

226. 翻转二叉树:

https://leetcode-cn.com/problems/invert-binary-tree

代码语言:javascript
复制
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* mirrorTree(TreeNode* root) {
        if (!root) {
            return root;
        }

        swap(root->left, root->right);

        mirrorTree(root->left);
        mirrorTree(root->right);

        return root;
    }
};

pair替代二元数据结构

有时候我们可能需要一些临时的数据结构。如果这个数据结构只有两个成员变量,那么你大可不必定义出来一个struct或class。直接上pair!比如这道:

38. 外观数列

https://leetcode-cn.com/problems/count-and-say

代码语言:javascript
复制
class Solution {
public:
    string countAndSay(int n) {
        string num = "1";
        for (int i = 1; i < n; ++i) {
            auto s = say(num);
            num.swap(s);
        }
        return num;
    }
    string say(const string& num) {
        vector<pair<char, int>> v;  // 直接用pair
        v.emplace_back(num[0], 1);
        for (int i = 1; i < num.size(); ++i) {
            if (v.back().first == num[i]) {
                v.back().second++;
            } else {
                v.emplace_back(num[i], 1); // pair对emplace友好
            }
        }

        stringstream ss;
        for (auto& pa: v) {
            ss<<pa.second<<pa.first-'0';
        }
        return ss.str();
    }
};

pair还有其他好处,那就是它自带 operator< 比较运算符。如果你的自定义类型需要排序的话,那么pair就不需要你自己写这个比较函数了。而自定义类型则需要。

而且pair的构造函数可以直接接受first和second的值做参数。这对于emplace或者emplace_back都很友好!

accumulate()求数组的和

代码语言:javascript
复制
int sum = accumulate(nums.begin(), nums.end(), 0);

partial_sum()部分求和

对于某些前缀和相关的题目,可以简化代码

代码语言:javascript
复制
    vector<int> v = {1,2,3,5,6,7};
    vector<int> pre;
    partial_sum(v.begin(), v.end(), back_inserter(pre));
    for (int i: pre) {
        cout<< i<<endl;
    }

输出:

代码语言:javascript
复制
1
3
6
11
17
24

min()和max()

比如我们一般怎么求最小值呢?

代码语言:javascript
复制
if (v[i][t] < v[f][t-1] + price) {
    v[i][t] = v[f][t-1] + price;
}

可以直接用std::min()来简化if else:

代码语言:javascript
复制
v[i][t] = min(v[i][t], v[f][t-1] + price)

工作中不太需要,刷题适合。如果你需要从三个数字中求最小值呢?加一层{}

代码语言:javascript
复制
val = min({a, b, c});

如果求最大值就用std::max()

max_element()和min_element()

如果要从一个数组中找出最大值呢?

一般我们可能这么写:

代码语言:javascript
复制
int val = -1; // 假设-1是肯定小于dp[i]的
for (int& v: dp) { // dp是vector<int> 类型
    if (v > val) {
        v = val;
    }
}
return val;

太长了,可以直接:

代码语言:javascript
复制
return *max_element(dp.begin(), dp.end()); // 这样写的前提是能保证dp不是空的,否则段错误!

二分查找相关

upper_bound()lower_bound()有时可以直接拿来解二分法相关的题目,避免自己手写出错。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程往事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 心理建设篇
    • 寻找标尺,让进步可衡量
      • 寻找小惊喜,给自己正反馈
        • 不要死磕,学会放弃
          • 好记性不如烂笔头
          • 刷题顺序篇
          • 网站/APP使用篇
            • 自定义测试用例
              • 高效安排刷题时间
              • Trick篇
                • 修改函数参数
                  • 调用待补全函数自身
                    • 给解题函数增加默认值
                    • 官方库提升刷题效率(C++)
                      • swap替代手写交换
                        • pair替代二元数据结构
                          • accumulate()求数组的和
                            • partial_sum()部分求和
                              • min()和max()
                                • max_element()和min_element()
                                  • 二分查找相关
                                  领券
                                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档