代码训练营总结篇章

数组篇

1. 二分法:

1. 写程序的时候,一般会用左闭右闭区间,或者左闭右开区间。

左闭右闭:while left <= right:             right = middle -1 

左闭右开: while left < right:              right = middle (反正取不到right)

2. 移除元素

数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。

题目:给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。

这题可以用快慢指针,等于val的快指针多走一步,然后用快指针的值覆盖慢指针的值。

3. 滑动窗口

滑动窗口解法:其实就是用一个循环来做两个for循环的事情。left等价于控制开始位置的for循环,right等价于控制结束位置的for循环。

链表篇:

1. 移除链表元素(虚拟头结点)

题目:给定一个链表和一个值,将链表中与值相等的节点删除。

因为删除头结点和其他节点的方式不同。导致代码不统一。加入一个虚拟头结点后,头结点就和其他节点一样了,就可以用统一的代码处理。

2. 反转链表类

题目:把一个列表翻转。

用prev current两个指针来实现。自己画图把逻辑理清楚,然后写一遍就好。

题目:将相邻的节点两两交换

这就比反转列表更提高难度了。要用更多个指针。还是一样,自己画图把逻辑理清楚,然后写一遍就好。

3. 链表相交&环形

题目:给出两个单链表的头结点,返回他们的相交节点。

既然相交,那尾部应该是一样的。那就求出两个链表的长度。求长度差N,长链表先走N步后,短链表的指针也出发。两指针相遇的点就是交点。

题目:判断链表是否有环。如果有环返回环的入口。

思路,创造一个两指针相遇在环入口节点的机会!

假设入口节点为x, 入环后再走y个点,快慢指针相遇,y再走z步又到入口节点x。则我们有2(x+y) = x + n(y+z) + y => x = (y+z) - y

这意味着,如果有个新指针2, 在环内先走了y步,然后另个一个指针1从head出发,两指针都走x步的时间,将会在环的入口相会。这就创造出了指针相等的条件。

哈希表篇

当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。

题目:两个单词,判断是否由相同的字母构成。

用一个字典统计字母频数即可。这里需要记住一个ord()函数

题目:两数相加

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

用字典储存。遍历一遍,如果num的补数(target - num)在字典内,则返回他们的数组下标。不在,就把num和对应的下标计入字典。

题目:三数之和 

给定一个长度超过3的数组,返回所有的三数组合 [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0. 答案中不含重复的三数组合。

排序后,最外层的循环是第一个数。然后在区间[i, n-1]里面用双指针,left, right。找三数之和为0.

题目:四数之和 I

将上一题的三数之和拓展为四数之和。三数组合是一层for循环,加一层左右指针。四数组合可以两层for循环,加一层左右指针。

题目:四数相加II

给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0。

和两数之和类似。AB相加的和放入一个set,然后计算-(C+D)看是否在set中。

字符串篇

1. 反转字符串

题目:将输入的字符串反转过来。你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

左右指针对应值互换即可

题目:给定一个字符串 s 和一个整数 k,从字符串开头算起, 每计数至 2k 个字符,就反转这 2k 个字符中的前 k 个字符。

定义一个翻转的函数,然后逐一处理每一段2k个字符。

2. 全部翻转+局部翻转

题目:给定一个字符串,逐个翻转字符串中的每个单词。

没啥把句子里的单词翻转的方法。那就把整个字符串全部翻转,然后每个单词内部翻转回去。

题目:右旋转字符串:给定一个字符串 s 和一个正整数 k,将字符串中的后面 k 个字符移到字符串的前面。

先这个字符串全部翻转,然后局部翻转:前k个字符翻转,剩下的翻转。

栈与队列篇

1. 栈和队列的相互转换

题目:用栈实现队列

思路:用两个栈实现队列。stack1存入,要pop前先转移元素到stack2, 此时stack2就类似队列了;接着把stack2栈顶的元素弹出即可。注意:在stack2清空前(也就是队列前面部分耗光前),不需要再做移动的操作。

题目:用队列实现栈

思路:用两个队列实现栈。q1存入。如果要弹出,就把q1元素移动到q2,然后剩最后一个元素,弹出。注意:移动完后,直接把q1 q2互换,不需要移回来。因为两个队列顺序都一样。

2. 栈的应用

题目:给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否合法。

思路:用字典把左右括号对应起来。碰到左括号入栈,右括号出栈。

题目:给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。

碰到与栈顶元素不一样的就入栈,碰到一样的就弹出。最后返回栈这个列表组成的字符串即可。

题目:逆波兰表达式求值

思路:碰到数字存入栈;碰到符号则弹出栈顶的两个元素,运算后的结果存入栈

3. 最小堆的应用

题目:给定一个非空的整数数组,返回其中出现频率前 k 高的元素。

思路:1. 要统计元素出现频率:用map统计频率;2. 对频率排序,用大顶堆排序;3. 找出前K个高频元素。

题目:给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。返回滑动窗口中的最大值。

思路:其实队列没有必要维护窗口里的所有元素,只需要维护有可能成为窗口里最大值的元素就可以了。移动窗口时候,是根据index移除,因此窗口里也维护index就好了。

二叉树篇

深度优先:前中后序遍历; 广度优先:层序遍历。要熟练掌握递归迭代的方法。

1.  求二叉树的属性

题目:给定一个二叉树,检查它是否是镜像对称的。

思路:1. 递归法:终止条件:if 左右都为空,对称,返回true;elif 有一个为空,不对称,return false;elif 左右都有值,但值不等,不对称 return false。递归条件:else 比较 left.left vs right.right 和 left.right vs right.left.

题目:二叉树的最大深度。 & n叉树的最大深度。

思路:迭代法:层序遍历。递归法,前序遍历。

题目:给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

思路:递归:终止条件:碰到叶节点则返回1. 递归条件:返回左子树(如果有)和右子树(如果有)的最小深度,取较小者。

题目:完全二叉树的节点个数

思路:完全二叉树只有两种情况,1:就是满二叉树,2:最后一层叶子节点没有满。但左子树或右子树一定有一个满二叉树。

对于情况一,可以直接用 2^树深度 - 1 来计算。对于情况二,左右孩子中,满二叉树的那个直接计算。而另一个进行递归。

题目:给定一个二叉树,判断它是否是高度平衡的二叉树。

思路:一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。

递归法:终止条件:如果根节点为空,返回True;如果左右子树高度差超过1,就返回False。递归条件:递归左右子树。迭代法一样。

题目:给定一个二叉树,返回从根节点到叶子节点的所有路径。叶子节点是指没有子节点的节点。

思路:需要记录路径,回溯算法最合适。

题目:计算给定二叉树的所有左叶子之和

思路:要注意是判断左叶子,不是二叉树左侧节点,所以不要上来想着层序遍历。简单的前序遍历即可。左叶子三个约束条件:1. 不是根节点 2. 是叶节点 3. 是父节点的左节点。 迭代的时候,根节点以下,把节点放入stack的时候,带上一个标签表示是否是左节点。

题目:给定一个二叉树,在树的最后一行找到最左边的值

思路:用层序遍历是非常简单的了,反而用递归的话会比较难一点。

这里的层序遍历,在每一层内部从右到左,保证最后一个节点是最左的节点。

题目:给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。112返回布尔值,113返回所有符合的路径。

思路:终止条件:到叶节点的时候,看路径上所有节点的值总和是否等于targetSum。如果相等,就把路径贴入结果。如果不是叶节点,就继续放进栈迭代。

2. 二叉树的修改与构造

题目翻转一棵二叉树。

思路:只要把每一个节点的左右孩子翻转一下,就可以达到整体翻转的效果。

这道题目使用前序遍历和后序遍历都可以,唯独中序遍历不方便,因为中序遍历会把某些节点的左右孩子翻转了两次!

题目:中序+前/后序 构造二叉树

思路:前序遍历第一个元素是根,后序遍历最后一个元素是根,中序遍历根元素左边是左子树,右边是右子树。

题目:给定一个不含重复元素的整数数组。构建最大二叉树

思路:最大二叉树的根是数组中的最大元素。左子树是通过数组中最大值左边部分构造出的最大二叉树。右子树是通过数组中最大值右边部分构造出的最大二叉树。与上一题一样。

题目合并二叉树 。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。

思路:递归法终止条件:两个root都为空,返回空;一个为空,返回另一个;递归条件:两个都不为空,root.val等于两个相加,左右节点递归。

迭代法:层序遍历比较方便。

3. 二叉搜索树的属性

题目:给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中搜索到节点值等于给定值的节点。 

思路:二分搜索法

题目:给定一个二叉树,验证其是否是一个有效的二叉搜索树。

思路:递归法和迭代法都很直观,见代码。还有一种做法是:二叉搜索树的中序遍历是递增序列(反之也成立)。

题目: 二叉搜索树中节点值之间的最小绝对差 

思路:搜索二叉树的中序遍历是递增数列。然后对递增序列求最小绝对差。用callback: callback其实就是把函数diff()作为参数传入中序遍历函数inorder_traversal()。

题目:二叉搜索树中的众数 

思路:依然是利用中序遍历转为递增数列。用callback把函数update_mode 作为参数传入遍历函数inorder_traversal()。

题目:把二叉搜索树转换为累加树 ,使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。

思路:可以用右中左逆中序遍历转为递减序列。这样只要从前往后累加就好了。

4. 二叉搜索树的修改与构造

题目:二叉搜索树中的插入操作 

思路:递归:和二分法查找类似。迭代:稍微麻烦点,需要记录父节点,插入的方向,这样才能做插入操作

题目删除二叉搜索树中的节点 

思路:1. 在二叉搜索树中找到该节点。如果是叶节点,直接删除;如果有一个左右节点,用左右子树代替当前节点;如果同时有左右节点,就去找右子树的最小值,把这个最小值填入当前节点。然后在右子树中,删除最小值节点(一定是叶节点)。

用迭代法要注意,如果删除子节点,要更新父节点对其的引用。因为二叉树节点是一个对象实例,而python 是没有办法立即释放一个对象的。我们只可以通过修改 父节点的 left 或 right 指针来解除对子节点的引用,而不能直接让子节点等于None而实现删除。

题目:给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>=L) 。

迭代法:用stack写有些麻烦,可以利用二叉搜索树的性质,最大和最小的节点都在最边上,只要把最边上超出范围的节点修剪去即可,不比遍历所有节点。不过这里最好用一个虚拟头结点才好处理。

递归法:如果当前节点超出右边界,就返回左节点;如果超出左边界,就返回右节点;如果不超出边界,就对左右节点递归使用函数。

题目:从一个递增数组,构造一棵高度平衡二叉搜索树。

思路:找出数组的中间节点为根节点。

5. 二叉树公共祖先问题

 题目:二叉树的最近公共祖先  

思路:递归法是最直观的:

终止条件:找到等于p or 找到等于q or 找到None,都返回node. 

递归条件:递归每个node的left和right,如果left right都有返回,则返回当前Node,如果只有left有返回,则返回left的返回,如果只有right也一样。

题目:二叉搜索树的最近公共祖先

思路:比普通二叉树更容易。但要注意,返回节点的终止条件是:min(p.val, q.val) <= root.val <= max(p.val, q.val),要取等。因为如果遍历到p或者q时候,另一个node一定在其子树上。

单调栈篇

通常一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。时间复杂度为O(n)。

题目:根据每日温度输出:要想观测到更高的气温,至少需要等待的天数。

思路:使用一个从栈底到栈顶递减的单调栈,while新元素 i 比栈顶的元素大,那就弹出栈顶元素x,那元素x距离第一个比自己大的元素就是 i-x.

题目:下一个更大元素 I

nums1 是 nums2 的子集(没有重复元素)。找出 nums1 中每个元素在 nums2 中的下一个比其大的值。

思路:和上一题几乎一模一样,就不过把元素放到了nums1而已。

题目:下一个更大元素II

给定一个循环数组,输出每个元素的下一个更大元素。

思路:还是单调栈的应用。只要循环两个数组长度即可。

题目:接雨水:给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

接雨水这题本质上是寻找左右第一个高于自己的柱子。用一个从栈低到栈顶递减的单调栈即可。

那雨水面积就是 water += (i - stack[-1] - 1) * (min(right, left) - mid)。这里要注意,头尾两侧没有柱子围着。如果stack pop到空,也就意味着此时没有左柱子围着了。那就要break。

题目:柱状图中最大的矩形。给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。

单调栈思路:最大矩形实际上就是寻找左右第一个低于自己的柱子。用一个从栈底到栈顶递增的单调栈即可。

那矩形面积就是:(right-left-1)*heights[mid] 。不过这里要注意,左右第一个柱子,没有更左或更右的低于自身的柱子。那就头尾加两个0好了。

回溯算法篇

代码模板:

题目太多就不总结了。看文章第20-26天。

以及卡哥总结 https://programmercarl.com/%E5%9B%9E%E6%BA%AF%E6%80%BB%E7%BB%93.html

贪心算法篇

看文章27-32。重点看31 32两天。

卡哥总结 https://programmercarl.com/%E8%B4%AA%E5%BF%83%E7%AE%97%E6%B3%95%E6%80%BB%E7%BB%93%E7%AF%87.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,406评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,976评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,302评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,366评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,372评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,457评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,872评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,521评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,717评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,523评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,590评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,299评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,859评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,883评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,127评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,760评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,290评论 2 342

推荐阅读更多精彩内容