本文的选题依据来自 https://cspiration.com/leetcodeClassification 中的划分,下面的序号以 Leetcode 英文版为准
⭐15.3Sum
- 该题的意思是给定一个数组和一个 target,找出数组中三数相加等于 target 的所有情况
- 该题的解法就是固定一个数字,然后找到除该数之外的一对数,看能否满足条件,此时问题退化为 2Sum 问题
- 该问题有几个核心:1、排序,这样才能保证在固定数字时不出现重复;2、排除固定重复元素,这里使用了通用方式 if(i>0&&nums[i]==nums[i-1])则 continue;也就是说当数字不是第一个元素的时候,遇到和前面相同的元素则跳过当前元素的查找,这个做法在全排列等问题中也经常使用;3、内循环中如果遇到满足条件的则加入 res 中,但此时仍然要注意排除重复情况,所以依然要判断 nums[low]和 nums[low+1]以及 nums[high]和 nums[high-1]之间的关系,如果遇到两个相同,则做相应处理,否则直接 low++同时 high–;
17.Letter Combinations of a Phone Number
- 该题涉及排列组合问题,使用队列解决。首先在 queue 中加入空字符,进入循环,假设输入的数字是 23,则第一次循环是为了加入输入的第一个数字 2,则此时 queue 中加入 abc,index=1;之后加入第二个数字 3,则此时 abc 依次出队,a 出队时加上了 def,则组成了 ad、ae、af,随后 b 出队,组成 bd、be、bf,最后 c 出队,组成 cd、ce、cf,至此两个长度的数字组成完毕,就能进行输出.
18.4Sum
- 该题和 3Sum 从解法和步骤上来说完全一致,只不过此处需要多使用一个循环对两个变量进行定位,之后再转化为 2Sum 问题,所以存在两个 for 循环,这两个循环都是为了确定固定元素,这两处都需要注意去重问题
20.Valid Parentheses
- 该题利用堆栈解决,没什么好说的
22.Generate Parentheses
- 该题使用深度优先遍历解决,利用 DFS 则需要考虑退出情况,这里是两个。一个是左符号的数量超过右符号,不满足条件;一个是左右符号数量同时为 0,此时可以输出一种情况。
- 之后就是利用深度优先先把左符号堆满,(((->((())),之后一个左符号退出((,这个时候轮到右符号堆满,分别组成(()())和(())(),以此类推
23.Merge k Sorted Lists
- 根据上图的演示可以很好理解这个题目的解法,这个题目使用最小堆来解决,由于堆的插入时间复杂度是 logk,所以总的时间复杂度是 nklogk(n 个元素、链表数量为 k)
- 这里需要重写 Comparator 方法,把头结点值较小的链表排在开头,然后从最小堆中取值,先取出链表,再从链表中取结点,此时取出的结点肯定是当前待取结点中最小的,取出之后就将该链表重新加入到最小堆中,此时又会重新排序,所以这样就能保证每次取出的都是最小,也就保证了有序
26.Remove Duplicates from Sorted Array
- 该题使用“双指针”解决,一个指针遍历全部数组,一个指针记录有多少单独元素,拿当前元素和前一个元素比较,如果相同则不处理,否则 count++并完成赋值
27.Remove Element
- 该题和上题一致,只不过把条件转换成和 val 的比较
28.Implement strStr()
- 该题除非使用 KMP 算法进行匹配,否则其余时间复杂度都是平方级别,所以直接使用 subString 函数解决问题
29.Divide Two Integers
- 该题主要需要注意异常处理,包括正负号、越界、等于 0(指的 3/5 这种小数情况而不是除数为 0 的情况),其余就是正常情况
- 要模拟除法操作一般就用减法逼近,但是如果逐次递减一般会超时,所以考虑使用乘法快速逼近,这个思想体现在了 divide 函数中。以 9/3 为例,最初 3+3<9,multiple+=multiple=2,之后进入递归(9-6,3),此时 3+3>3,multiple=1,所以退出递归,multiple 返回 3