GithubHelp home page GithubHelp logo

youngyangyang04 / leetcode-master Goto Github PK

View Code? Open in Web Editor NEW
47.3K 374.0 10.9K 95.49 MB

《代码随想录》LeetCode 刷题攻略:200道经典题目刷题顺序,共60w字的详细图解,视频难点剖析,50余张思维导图,支持C++,Java,Python,Go,JavaScript等多语言版本,从此算法学习不再迷茫!🔥🔥 来看看,你会发现相见恨晚!🚀

Shell 100.00%
leetcode programmer interview offer algorithm cpp java python go javascript

leetcode-master's Introduction

👉 推荐 在线阅读 (Github在国内访问经常不稳定)
👉 推荐 Gitee同步

  1. 介绍 :本项目是一套完整的刷题计划,旨在帮助大家少走弯路,循序渐进学算法,关注作者
  2. 正式出版《代码随想录》
  3. PDF版本「代码随想录」算法精讲 PDF 版本
  4. 算法公开课《代码随想录》算法视频公开课
  5. 最强八股文代码随想录知识星球精华PDF
  6. 刷题顺序 :README已经将刷题顺序排好了,按照顺序一道一道刷就可以。
  7. 学习社区 :一起学习打卡/面试技巧/如何选择offer/大厂内推/职场规则/简历修改/技术分享/程序人生。欢迎加入「代码随想录」知识星球
  8. 提交代码 :本项目统一使用C++语言进行讲解,但已经有Java、Python、Go、JavaScript等等多语言版本,感谢这里的每一位贡献者,如果你也想贡献代码点亮你的头像,点击这里了解提交代码的方式。
  9. 转载须知 :以下所有文章皆为我(程序员Carl)的原创。引用本项目文章请注明出处,发现恶意抄袭或搬运,会动用法律武器维护自己的权益。让我们一起维护一个良好的技术创作环境!

LeetCode 刷题攻略

刷题攻略的背景

很多刚开始刷题的同学都有一个困惑:面对leetcode上近两千道题目,从何刷起。

大家平时刷题感觉效率低,浪费的时间主要在三点:

  • 找题
  • 找到了不应该现阶段做的题
  • 没有全套的优质题解可以参考

其实我之前在知乎上回答过这个问题,回答内容大概是按照如下类型来刷数组-> 链表-> 哈希表->字符串->栈与队列->树->回溯->贪心->动态规划->图论->高级数据结构,再从简单刷起,做了几个类型题目之后,再慢慢做中等题目、困难题目。

但我能设身处地的感受到:即使有这样一个整体规划,对于一位初学者甚至算法老手寻找合适自己的题目也是很困难,时间成本很高,而且题目还不一定就是经典题目。

对于刷题,我们都是想用最短的时间按照循序渐进的难度顺序把经典题目都做一遍,这样效率才是最高的!

所以我整理了leetcode刷题攻略:一个超级详细的刷题顺序,每道题目都是我精心筛选,都是经典题目高频面试题,大家只要按照这个顺序刷就可以了,你没看错,README已经把题目顺序都排好了,文章顺序就是刷题顺序!挨个刷就可以,不用自己再去题海里选题了!

而且每道题目我都写了的详细题解(图文并茂,难点配有视频),力扣上我的题解都是排在对应题目的首页,质量是有目共睹的。

那么现在我把刷题顺序都整理出来,是为了帮助更多的学习算法的同学少走弯路!

如果你在刷leetcode,强烈建议先按照本攻略刷题顺序来刷,刷完了你会发现对整个知识体系有一个质的飞跃,不用在题海茫然的寻找方向。

最新文章会首发在公众号「代码随想录」,扫码看看吧,你会发现相见恨晚!

如何使用该刷题攻略

按照先面的排列顺序,从数组开始刷起就可以了,顺序都安排好了,按顺序刷就好。

在刷题攻略中,每个专题开始都有理论基础篇,并不像是教科书般的理论介绍,而是从实战中归纳需要的基础知识。每个专题结束都有总结篇,最这个专题的归纳总结。

如果你是算法老手,这篇攻略也是复习的最佳资料,如果把每个系列对应的总结篇,快速过一遍,整个算法知识体系以及各种解法就重现脑海了。

这里每一篇题解,都是精品,值得仔细琢磨

我在题目讲解中统一使用C++,但你会发现下面几乎每篇题解都配有其他语言版本,Java、Python、Go、JavaScript等等,正是这些热心小伙们贡献的代码,当然我也会严格把控代码质量。

所以也欢迎大家参与进来,完善题解的各个语言版本,拥抱开源,让更多小伙伴们受益

准备好了么,刷题攻略开始咯,go go go!


前序

数组

  1. 数组过于简单,但你该了解这些!
  2. 数组:704.二分查找
  3. 数组:27.移除元素
  4. 数组:977.有序数组的平方
  5. 数组:209.长度最小的子数组
  6. 数组:59.螺旋矩阵II
  7. 数组:总结篇

链表

  1. 关于链表,你该了解这些!
  2. 链表:203.移除链表元素
  3. 链表:707.设计链表
  4. 链表:206.翻转链表
  5. 链表:24.两两交换链表中的节点
  6. 链表:19.删除链表的倒数第 N 个结点
  7. 链表:链表相交
  8. 链表:142.环形链表
  9. 链表:总结篇!

哈希表

  1. 关于哈希表,你该了解这些!
  2. 哈希表:242.有效的字母异位词
  3. 哈希表:1002.查找常用字符
  4. 哈希表:349.两个数组的交集
  5. 哈希表:202.快乐数
  6. 哈希表:1.两数之和
  7. 哈希表:454.四数相加II
  8. 哈希表:383.赎金信
  9. 哈希表:15.三数之和
  10. 双指针法:18.四数之和
  11. 哈希表:总结篇!

字符串

  1. 字符串:344.反转字符串
  2. 字符串:541.反转字符串II
  3. 字符串:替换数字
  4. 字符串:151.翻转字符串里的单词
  5. 字符串:右旋字符串
  6. 帮你把KMP算法学个通透
  7. 字符串:459.重复的子字符串
  8. 字符串:总结篇!

双指针法

双指针法基本都是应用在数组,字符串与链表的题目上

  1. 数组:27.移除元素
  2. 字符串:344.反转字符串
  3. 字符串:替换数字
  4. 字符串:151.翻转字符串里的单词
  5. 链表:206.翻转链表
  6. 链表:19.删除链表的倒数第 N 个结点
  7. 链表:链表相交
  8. 链表:142.环形链表
  9. 双指针:15.三数之和
  10. 双指针:18.四数之和
  11. 双指针:总结篇!

栈与队列

  1. 栈与队列:理论基础
  2. 栈与队列:232.用栈实现队列
  3. 栈与队列:225.用队列实现栈
  4. 栈与队列:20.有效的括号
  5. 栈与队列:1047.删除字符串中的所有相邻重复项
  6. 栈与队列:150.逆波兰表达式求值
  7. 栈与队列:239.滑动窗口最大值
  8. 栈与队列:347.前K个高频元素
  9. 栈与队列:总结篇!

二叉树

题目分类大纲如下:
二叉树大纲

  1. 关于二叉树,你该了解这些!
  2. 二叉树:二叉树的递归遍历
  3. 二叉树:二叉树的迭代遍历
  4. 二叉树:二叉树的统一迭代法
  5. 二叉树:二叉树的层序遍历
  6. 二叉树:226.翻转二叉树
  7. 本周小结!(二叉树)
  8. 二叉树:101.对称二叉树
  9. 二叉树:104.二叉树的最大深度
  10. 二叉树:111.二叉树的最小深度
  11. 二叉树:222.完全二叉树的节点个数
  12. 二叉树:110.平衡二叉树
  13. 二叉树:257.二叉树的所有路径
  14. 本周总结!(二叉树)
  15. 二叉树:二叉树中递归带着回溯
  16. 二叉树:404.左叶子之和
  17. 二叉树:513.找树左下角的值
  18. 二叉树:112.路径总和
  19. 二叉树:106.构造二叉树
  20. 二叉树:654.最大二叉树
  21. 本周小结!(二叉树)
  22. 二叉树:617.合并两个二叉树
  23. 二叉树:700.二叉搜索树登场!
  24. 二叉树:98.验证二叉搜索树
  25. 二叉树:530.搜索树的最小绝对差
  26. 二叉树:501.二叉搜索树中的众数
  27. 二叉树:236.公共祖先问题
  28. 本周小结!(二叉树)
  29. 二叉树:235.搜索树的最近公共祖先
  30. 二叉树:701.搜索树中的插入操作
  31. 二叉树:450.搜索树中的删除操作
  32. 二叉树:669.修剪二叉搜索树
  33. 二叉树:108.将有序数组转换为二叉搜索树
  34. 二叉树:538.把二叉搜索树转换为累加树
  35. 二叉树:总结篇!(需要掌握的二叉树技能都在这里了)

回溯算法

题目分类大纲如下:

回溯算法大纲

  1. 关于回溯算法,你该了解这些!
  2. 回溯算法:77.组合
  3. 回溯算法:77.组合优化
  4. 回溯算法:216.组合总和III
  5. 回溯算法:17.电话号码的字母组合
  6. 本周小结!(回溯算法系列一)
  7. 回溯算法:39.组合总和
  8. 回溯算法:40.组合总和II
  9. 回溯算法:131.分割回文串
  10. 回溯算法:93.复原IP地址
  11. 回溯算法:78.子集
  12. 本周小结!(回溯算法系列二)
  13. 回溯算法:90.子集II
  14. 回溯算法:491.递增子序列
  15. 回溯算法:46.全排列
  16. 回溯算法:47.全排列II
  17. 本周小结!(回溯算法系列三)
  18. 回溯算法去重问题的另一种写法
  19. 回溯算法:332.重新安排行程
  20. 回溯算法:51.N皇后
  21. 回溯算法:37.解数独
  22. 回溯算法总结篇

贪心算法

题目分类大纲如下:

贪心算法大纲

  1. 关于贪心算法,你该了解这些!
  2. 贪心算法:455.分发饼干
  3. 贪心算法:376.摆动序列
  4. 贪心算法:53.最大子序和
  5. 本周小结!(贪心算法系列一)
  6. 贪心算法:122.买卖股票的最佳时机II
  7. 贪心算法:55.跳跃游戏
  8. 贪心算法:45.跳跃游戏II
  9. 贪心算法:1005.K次取反后最大化的数组和
  10. 本周小结!(贪心算法系列二)
  11. 贪心算法:134.加油站
  12. 贪心算法:135.分发糖果
  13. 贪心算法:860.柠檬水找零
  14. 贪心算法:406.根据身高重建队列
  15. 本周小结!(贪心算法系列三)
  16. 贪心算法:406.根据身高重建队列(续集)
  17. 贪心算法:452.用最少数量的箭引爆气球
  18. 贪心算法:435.无重叠区间
  19. 贪心算法:763.划分字母区间
  20. 贪心算法:56.合并区间
  21. 本周小结!(贪心算法系列四)
  22. 贪心算法:738.单调递增的数字
  23. 贪心算法:968.监控二叉树
  24. 贪心算法:总结篇!(每逢总结必经典)

动态规划

动态规划专题已经开始啦,来不及解释了,小伙伴们上车别掉队!

  1. 关于动态规划,你该了解这些!
  2. 动态规划:509.斐波那契数
  3. 动态规划:70.爬楼梯
  4. 动态规划:746.使用最小花费爬楼梯
  5. 本周小结!(动态规划系列一)
  6. 动态规划:62.不同路径
  7. 动态规划:63.不同路径II
  8. 动态规划:343.整数拆分
  9. 动态规划:96.不同的二叉搜索树
  10. 本周小结!(动态规划系列二)

背包问题系列:

背包问题大纲

  1. 动态规划:01背包理论基础
  2. 动态规划:01背包理论基础(滚动数组)
  3. 动态规划:416.分割等和子集
  4. 动态规划:1049.最后一块石头的重量II
  5. 本周小结!(动态规划系列三)
  6. 动态规划:494.目标和
  7. 动态规划:474.一和零
  8. 动态规划:完全背包总结篇
  9. 动态规划:518.零钱兑换II
  10. 本周小结!(动态规划系列四)
  11. 动态规划:377.组合总和Ⅳ
  12. 动态规划:70.爬楼梯(完全背包版本)
  13. 动态规划:322.零钱兑换
  14. 动态规划:279.完全平方数
  15. 本周小结!(动态规划系列五)
  16. 动态规划:139.单词拆分
  17. 动态规划:多重背包理论基础
  18. 背包问题总结篇

打家劫舍系列:

  1. 动态规划:198.打家劫舍
  2. 动态规划:213.打家劫舍II
  3. 动态规划:337.打家劫舍III

股票系列:

股票问题总结

  1. 动态规划:121.买卖股票的最佳时机
  2. 动态规划:本周小结(系列六)
  3. 动态规划:122.买卖股票的最佳时机II
  4. 动态规划:123.买卖股票的最佳时机III
  5. 动态规划:188.买卖股票的最佳时机IV
  6. 动态规划:309.最佳买卖股票时机含冷冻期
  7. 动态规划:本周小结(系列七)
  8. 动态规划:714.买卖股票的最佳时机含手续费
  9. 动态规划:股票系列总结篇

子序列系列:

  1. 动态规划:300.最长递增子序列
  2. 动态规划:674.最长连续递增序列
  3. 动态规划:718.最长重复子数组
  4. 动态规划:1143.最长公共子序列
  5. 动态规划:1035.不相交的线
  6. 动态规划:53.最大子序和
  7. 动态规划:392.判断子序列
  8. 动态规划:115.不同的子序列
  9. 动态规划:583.两个字符串的删除操作
  10. 动态规划:72.编辑距离
  11. 编辑距离总结篇
  12. 动态规划:647.回文子串
  13. 动态规划:516.最长回文子序列
  14. 动态规划总结篇

单调栈

  1. 单调栈:739.每日温度
  2. 单调栈:496.下一个更大元素I
  3. 单调栈:503.下一个更大元素II
  4. 单调栈:42.接雨水
  5. 单调栈:84.柱状图中最大的矩形

图论

通知:开始更新图论内容,图论部分还没有其他语言版本,欢迎录友们提交PR,成为contributor

深搜广搜

(持续更新中....)

十大排序

数论

高级数据结构经典题目

  • 并查集
  • 最小生成树
  • 线段树
  • 树状数组
  • 字典树

海量数据处理

补充题目

以上题目是重中之重,大家至少要刷两遍以上才能彻底理解,如果熟练以上题目之后还在找其他题目练手,可以再刷以下题目:

这些题目很不错,但有的题目是和刷题攻略类似的,有的题解后面还会适当补充,所以我还没有将其纳入到刷题攻略。一些题解等日后我完善一下,再纳入到刷题攻略。

数组

链表

哈希表

字符串

二叉树

回溯算法

贪心

动态规划

图论

并查集

模拟

位运算

算法模板

各类基础算法模板

贡献者

点此这里查看LeetCode-Master的所有贡献者。感谢他们补充了LeetCode-Master的其他语言版本,让更多的读者受益于此项目。

Star 趋势

Star History Chart

关于作者

大家好,我是程序员Carl,哈工大师兄,《代码随想录》作者,先后在腾讯和百度从事后端技术底层技术研发。

PDF下载

添加如下企业微信,会自动发送给大家PDF版本,顺便可以选择是否加入刷题群。

添加微信记得备注,如果是已工作,备注:姓名-城市-岗位。如果学生,备注:姓名-学校-年级。备注没有自我介绍不通过哦

leetcode-master's People

Contributors

bqlin avatar casnz1601 avatar cezarbbb avatar eeee0717 avatar fengxiuyang avatar flames519 avatar fusunx avatar fwqaaq avatar gaoyangu avatar hailincai avatar ironartisan avatar jerry-306 avatar jerryfishcode avatar jianghongcheng avatar jinbudaily avatar jojoo15 avatar joshua-lu avatar juguagua avatar kingarthur0205 avatar liangdazhu avatar lozakaka avatar nanhuaibeian avatar posper98 avatar quinndk avatar wzqwtt avatar x-shuffle avatar xiaofei-2020 avatar ydlin avatar youngyangyang04 avatar z80160280 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

leetcode-master's Issues

226 翻转二叉树 中序遍历

翻转二叉树可用中序遍历来做,只是翻转之后依然进入左子树递归

class Solution {
public:
    void invert (TreeNode* cur){
        if (cur!=nullptr){
            invert(cur->left);
            swap(cur->left, cur->right);
            invert(cur->left);
        }
    }
    TreeNode* invertTree(TreeNode* root) {
        invert(root);
        return root;
    }
};

N皇后判断在斜线上的方法

如果两个皇后位于某条斜线,那么只有两种情况:1.两个皇后的行-列的差相等。2.两个皇后的行+列的和相等,根据这个特性,不难写出如下代码:


// #51 N皇后问题
class Solution {
	vector<vector<string>> result;
	vector<string> curPath;
	void solveNQueensIter(int curRow, int targetRow, vector<int>& usedCol, unordered_set<int>& usedDiff, unordered_set<int>& usedSum) {
		if (curRow == targetRow) {
			result.emplace_back(curPath);
			return;
		}
		for (int curCol = 0; curCol < targetRow; curCol++) {
			if (usedCol[curCol] == 1) continue;
			if (usedDiff.find(curRow - curCol) != usedDiff.end()) continue;
			if (usedSum.find(curRow + curCol) != usedSum.end()) continue;
			string path(targetRow, '.' );
			path[curCol] = 'Q';
			curPath.emplace_back(path);
			usedCol[curCol] = 1;
			usedDiff.insert(curRow - curCol);
			usedSum.insert(curRow + curCol);
			solveNQueensIter(curRow + 1, targetRow, usedCol, usedDiff, usedSum);
			usedDiff.erase(curRow - curCol);
			usedSum.erase(curRow + curCol);
			usedCol[curCol] = 0;
			curPath.pop_back();
		}
	}
public:
	vector<vector<string>> solveNQueens(int n) {
		vector<int> usedCol(n, 0);
		unordered_set<int> usedDiff, usedSum;
		solveNQueensIter(0, n, usedCol, usedDiff, usedSum);
		return result;
	}
};

101题.对称二叉树

个人感觉这个也不完全是后序遍历,因为每到一棵树上,都会先判断根节点的值是否相等,是否可以理解为是一种先序遍历和剪枝的操作

[Python 代码更新] 链表:听说用虚拟头节点会方便很多?

原作的写法感觉比较偏Java,其中部分语法不符合Python的新特性。为了凸显Python语法的简便性,附上改写后的Python代码。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next

class Solution:
    def removeElements(self, head: ListNode, val: int) -> ListNode:
        dummy_head = ListNode(0, head)
        cur = dummy_head

        while cur.next:
            if cur.next.val == val:
                cur.next = cur.next.next
            else:
                cur = cur.next
        return dummy_head.next
       

贪心算法:无重叠区间(435),Java第一段代码无法通过测试

屏幕截图 2021-08-23 220041

问题在于intervals排序中if判断条件错误,应该对o1[1]和o2[1]进行判断,而不是o1[0]和o2[0]。
修改后可以通过所有测试,

class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        if (intervals.length < 2) return 0;
        Arrays.sort(intervals, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                if (o1[1] != o2[1]) {
                    return Integer.compare(o1[1],o2[1]);
                } else {
                    return Integer.compare(o2[0],o1[0]);
                }
            }
        });

        int count = 0;
        int edge = intervals[0][1];
        for (int i = 1; i < intervals.length; i++) {
            if (intervals[i][0] < edge) {
                count++;
            } else {
                edge = intervals[i][1];
            }
        }
        return count;
    }
}

二叉树是否需要返回值

在left = ...,right =... ,格式中,判断是否是平衡树时,是可以提前结束的,不需要遍历整个二叉树呀。

59.螺旋矩陣II 能夠用有規劃的方式寫出更好的解法!

class Solution {
public:
int dirs[4][2] = {{0,1}, {1,0}, {0,-1},{-1,0}};

vector<vector<int>> generateMatrix(int n) {

    vector<vector<int>> M;
    M.resize(n, vector<int>(n, 0));
    int final_num = n*n;
    int start = 1;
    int i = 0;
    int r,c;
    r=c=0;
    while(start <= final_num){
        M[r][c] = start++;
        if(r + dirs[i][0] < n && 
           c + dirs[i][1] < n && 
          r + dirs[i][0] >= 0 && 
           c + dirs[i][1] >= 0 && 
           M[r + dirs[i][0]][c + dirs[i][1]] == 0){
            r = r + dirs[i][0];
            c = c + dirs[i][1];
        }else{
            i = (i+1) % 4;
            r = r + dirs[i][0];
            c = c + dirs[i][1];
        }
    }
    return M;    
}   

};

位运算

您好,能出一个位运算专栏嘛!

0063.不同路径II的Java代码

链接:https://github.com/youngyangyang04/leetcode-master/blob/master/problems/0063.%E4%B8%8D%E5%90%8C%E8%B7%AF%E5%BE%84II.md
这一块的Java代码,可以使用我这个,和你的比较贴合,也对容易进坑的地方加了注释

public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        //起点可能就是障碍物,所以要特判,不特判也可以,看下面
//        if (obstacleGrid[0][0] == 1){
//            return 0;
//        }
        int m = obstacleGrid.length, n = obstacleGrid[0].length;
        int[][] dp = new int[m][n];
        //遇到障碍了,下面的就不用执行了
        for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) {
            dp[i][0] = 1;
        }
        //因为dp[0][0]上一个已经赋值了,所以这里要从1开始(这里也从0开始,就不需要特判)
        for (int i = 0; i < n && obstacleGrid[0][i] == 0; i++) {
            dp[0][i] = 1;
        }
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                //如果这里是障碍物,就取0
                //因为默认就是0,所以可以不赋值,节省时间
//                dp[i][j] = obstacleGrid[i][j] == 1 ? 0 : dp[i - 1][j] + dp[i][j - 1];
                if (obstacleGrid[i][j] == 1) {
                    continue;
                }
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[m - 1][n - 1];
    }

刷题顺序

您好,您的项目非常的棒。我想问一下刷题的顺序是从哪里看。是problems文件夹下面开始吗。我看了下,里面都是按照leetcode的顺序排列而已,以组合的题为例子,应该是先放组合77这道题,可是在刷的过程中39就先出现了。有点困惑

四数之和

C++的题解在测试样例
[1000000000, 1000000000, 1000000000, 1000000000]
0
LeetCode会报错溢出Int,
所以需要用(long long)作类型转换

93.复原ip地址python第一版代码运行失败

原版代码跑完提交失败,应该是return的位置错了,更改后提交成功
class Solution(object):
def restoreIpAddresses(self, s):
ans = []
path = []
def backtrack(path, startIndex):
if len(path) == 4:
if startIndex == len(s):
ans.append(".".join(path[:]))
return # 更改此处
for i in range(startIndex, min(startIndex+4, len(s)+1)): # 剪枝
string = s[startIndex:i+1]
if not 0 <= int(string) <= 255:
continue
if not string == "0" and not string.lstrip('0') == string:
continue
path.append(string)
backtrack(path, i+1)
path.pop()

    backtrack(s, 0)
    return ans

面试题 02.07. 链表相交 这题可以用双指针无需计算链表长度

通过交换指针位置来让指针达到同一个位置

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) return null;
        ListNode pA = headA;
        ListNode pB = headB;
        while (true) {
            if (pA == null && pB == null) return null;
            if (pA == null) {
                pA = headB;
            }
            if (pB == null) {
                pB = headA;
            }
            if (pA == pB) return pB;
            pA = pA.next;
            pB = pB.next;
        }
    }
}

leetcode150逆波兰表达式的建议

1、判断==的地方需要改成equals比较内容是否相同
2、isOpe函数可以加一行注释解释为什么需要判断length==1,因为有负数这样的例子,比如-11,不能算作运算符。

关于动态规划的746题最小花费爬台阶数的建议

感觉卡尔哥那里的解法有点抽象,可以看看我的,应该好理解一些

int minCostClimbingStairs(vector& cost) {
int n = cost.size();
//递归只需要前面两个台阶,所以长度为2的数组就足够了。
int dp[2];
dp[0] = 0;
dp[1] = 0;
//题目说了要爬到顶,也就是离开最高的台阶,所以我们就要爬到循环到=n,加上初始化的两次也就是多一次,正好跳出台阶
for(int i = 2; i <= n; ++i)
{
int tmp = dp[1];
//可以从前一个台阶花费前一个台阶的价格爬一步,也可以从前面第二个台阶花费它的价格爬两部。
dp[1] = min(dp[1] + cost[i-1], dp[0] + cost[i-2]);
dp[0] = tmp;
}
//dp[1]永远是最高的台阶,直接返回即可
return dp[1];
}

383. 赎金信 Java解法

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        if(magazine.length()==0) return ransomNote.length==0;
        int[] leter = new int[26];
        for(char c:magazine.toCharArray()){
            leter[c-'a'] += 1;
        }
        for(char a:ransomNote.toCharArray()){
            leter[a-'a'] -= 1;
            if(leter[a-'a']<0)
                return false;
        }
        return true;
    }
}

解数独问题可以只用一层for循环

解数独问题可以看成每次递归解决一个空格,也就是从1-9中选择一个输入填入当前空格,然后递归进去下一个空格。判断行列小正方格中是否出现也可以使用3个二维数组解决,避免使用for循环。代码如下:

// #37 解数独
class Solution {
private:
	vector<vector<int>> usedRowNum = vector<vector<int>>(9, vector<int>(9));
	vector<vector<int>> usedColNum = vector<vector<int>>(9, vector<int>(9));
	vector<vector<int>> usedQurNum = vector<vector<int>>(9, vector<int>(9));
	vector<vector<char>> result;
	bool solveSudoIter(vector<vector<char>>& board, int curRow, int curCol) {
		if (curRow == 9)
		{
			result = board;
			return true;
		}
		if (board[curRow][curCol] != '.') {
			return solveSudoIter(board, curRow + (curCol + 1) / 9, (curCol + 1) % 9);
		}
		for (int num = 0; num < 9; num++) {
			if (usedRowNum[curRow][num] == 1) continue;
			if (usedColNum[curCol][num] == 1) continue;
			int curQur = 3 * (curRow / 3) + curCol / 3;
			if (usedQurNum[curQur][num] == 1) continue;
			

			//push
			usedRowNum[curRow][num] = 1;
			usedColNum[curCol][num] = 1;
			usedQurNum[curQur][num] = 1;
			board[curRow][curCol] = '1' + num;

			// iter
			bool ifFound = solveSudoIter(board, curRow + (curCol + 1) / 9, (curCol + 1) % 9);
			if (ifFound) return true;

			//pop back
			usedRowNum[curRow][num] = 0;
			usedColNum[curCol][num] = 0;
			usedQurNum[curQur][num] = 0;
			board[curRow][curCol] = '.';
		}
		return false;
	}
public:
	void solveSudoku(vector<vector<char>>& board) {
		for (int row = 0; row < 9; row++) {
			for (int col = 0; col < 9; col++)
			{
				if (board[row][col] == '.') continue;
				int curNum = board[row][col] - '1';
				usedRowNum[row][curNum] = 1;
				usedColNum[col][curNum] = 1;
				int curQur = 3 * (row / 3) + col/3;
				usedQurNum[curQur][curNum] = 1;
			}
		}
		solveSudoIter(board, 0, 0);
	}
};

0583.两个字符串的删除操作

word1[i]!=word2[j]时只要考虑两种情况

  • dp[i-1][j]+1
  • dp[i][j-1]+1

dp[i-1][j-1]+2包含在上述情况中了

if(word1[i]==word2[j]){
        dp[i][j]=dp[i-1][j-1];
 }
  else{
         dp[i][j]=min(dp[i-1][j],dp[i][j-1])+1;
 }

关于 0-1 背包的理解问题

对于 0-1 背包问题上的滑动数组写法时,我有一个自己的理解,不知道是否正确。

假设有物体 j 个,每个物体的价值为value[j],重量为weight[ j ],那么对于一个背包 dp[ i ]
可以知道
dp[ i ] = max{dp[ i ], dp[ i - weight[ j ] + value[ j ]]}

相当于是说,这个背包可以由多个小背包推导出来,由哪几个小背包推导出来?就是 i - weight[ i ] 的这几个小背包,然后在里面挑选一个最大的值,初始化的过程应该也是相似的,即 dp[0] = 0;然后如果 i - weight[ i ] <= 0 说明没有这种小背包,直接continue;

您觉得这样理解可以吗~

188.买卖股票的最佳时机IV java版本答案空间可以进一步优化

个人感觉还可以进一步优化,有错望指正,力扣已AC。

class Solution {
    public int maxProfit(int k, int[] prices) {
        if(prices.length==0)return 0;
        int[] res=new int[2*k+1];
        for (int i = 1; i <2*k ; i+=2) {
            res[i]=-prices[0];
        }
        for (int i = 0; i <prices.length ; i++) {
            for (int j = 1; j <2*k ; j+=2) {
                res[j]=Math.max(res[j],res[j-1]-prices[i]);
                res[j+1]=Math.max(res[j+1],res[j]+prices[i]);
            }
        }
        return res[2*k];
    }
}

377. 组合总和 Ⅳ: 初始化dp[0] = 0

class Solution {
public:
int combinationSum4(vector& nums, int target) {
vector dp(target+1, 0);

    for (int t = 0; t < target + 1; ++ t) {
        for (int x : nums) {
            
            if (t >=x && dp[t]  <= INT_MAX - dp[t-x]) {
            
                if (t > x) dp[t] += dp[t-x];

                if (t == x && dp[t]  <= INT_MAX - 1) {
                    dp[t] += 1; //当前这个数字可以组成一个集合 满足target
                }
            }
        }
    }
    return dp[target];
}

};

#406 根据身高重建队列的另一种类似解法(也是贪心解法)

  1. 按照身高从低到高排序,身高相同,k大的排在前面
  2. 从后往前搜索,将每一个people往后移动k次

这样做能达到目的的原因是:当我们先将身高从低到高排序,任意元素往后移动,并不会影响后面元素的合理性。
并且,不需要额外空间存储,也就不需要是用链表。空间复杂度是O(1)

class Solution {
	static bool peopleCompare(vector<int>& pre, vector<int>& next) {
		if (pre[0] != next[0]) return pre[0] < next[0];
		else
		{
			return pre[1] > next[1];
		}
	}
public:
	vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
		sort(people.begin(), people.end(), peopleCompare);

		int preHeight = people[people.size() - 1][0];
		for (int i = people.size() - 1; i >= 0; i--) {
			int swapTime = people[i][1];
			for (int j = 0; j < swapTime; j++) {
				swap(people[i + j], people[i + j + 1]);
			}
		}
		return people;
	}
};

图论算法

希望能更一下图论算法的解题技巧,最近一直摸不到头难,辛苦Carl了!!

0209.长度最小的子数组.md

究竟为什么会出现两次 sum = 0???

class Solution {
public:
int minSubArrayLen(int s, vector& nums) {
int result = INT32_MAX; // 最终的结果
int sum = 0; // 子序列的数值之和
int subLength = 0; // 子序列的长度
for (int i = 0; i < nums.size(); i++) { // 设置子序列起点为i
sum = 0;

二叉树的统一迭代法 建议

完全没有必要将null添加到栈中,因为执行过if中的语句后,下一次循环必然执行else中的语句。
所以可以将代码放到一次循环中。

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if(root==null) return res;
        Deque<TreeNode> deque = new LinkedList<>();
        TreeNode cur = root;
        deque.push(cur);
        while (!deque.isEmpty()){
            cur = deque.peek();
            if (cur!=null){
                deque.pop();
                if (cur.right!=null) deque.push(cur.right);
                if (cur.left!=null) deque.push(cur.left);
                deque.push(cur);
                cur = deque.peek();
                deque.pop();
                if (cur != null) res.add(cur.val);
            }
        }
        return res;
    }
}

0072.编辑距离的操作一和操作二的解释似乎有问题

最近按照大佬的思路刷题进步很快,但是重新刷到编辑距离的时候我的理解有出入,希望大佬指正

操作一:word1增加一个元素,使其word1[i - 1]与word2[j - 1]相同,那么就是以下标i-2为结尾的word1 与 j-1为结尾的word2的最近编辑距离 加上一个增加元素的操作。
即 dp[i][j] = dp[i - 1][j] + 1;

这里dp[i - 1][j]表示以下标i - 2结尾的word1已经变换为以j - 1为结尾的word2的最近编辑距离,由于word1的i - 1下标元素与word2的j -1元素不等,所以需要删除word1中i - 1位置的元素,即word1删除一个元素

操作二:word2添加一个元素,使其word1[i - 1]与word2[j - 1]相同,那么就是以下标i-1为结尾的word1 与 j-2为结尾的word2的最近编辑距离 加上一个增加元素的操作。
即 dp[i][j] = dp[i][j - 1] + 1;

同理,因为word1中到i - 1位置的全部元素已经变换为了以j - 2为下标的word2,由于word1中i - 1位置的元素和word2中j - 1位置的元素不相等,所以需要对word1增加word2中j - 1位置的元素,即word1增加一个元素或者word2减少一个元素

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.