138.随机链表的复制
哈希表:利用哈希表来存储旧结点和新节点的对应关系,注意要用get方法来正确处理空值。遍历两次链表,第一次复制结点,第二次建立指针关系
148.排序链表
归并排序:分为两个部分,分割和合并。使用快慢指针的方法找到中间结点并一分为二,分别对两个链表排序,并合并 。合并时需要建立一个虚拟指针和一个尾指针,尾指针始终指向结果链表的末尾,两个链表中较小元素连接到尾指针后面,最终把剩余元素全部接到尾指针的部分
class Solution:
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
def merge(left,right):
dummy=ListNode(None)
tail=dummy
while left and right:
if left.val<right.val:
tail.next=left
left=left.next
else:
tail.next=right
right=right.next
tail=tail.next
if left:
tail.next=left
if right:
tail.next=right
return dummy.next
#or 不是 and,否则递归不会终止
if not head or not head.next:
return head
slow,fast=head,head.next
while fast and fast.next:
slow=slow.next
fast=fast.next.next
second=slow.next
slow.next=None
first=head
first=self.sortList(first)
second=self.sortList(second)
return merge(first,second)
105.从前序遍历和中序遍历序列构造二叉树
前序遍历中的第一个结点为根节点,在中序遍历中找到根节点的下标,写出左右子树的前序和中序遍历序列,从而递归的构造左右子树
437.路径总和Ⅲ
法一:前缀和+哈希表
哈希表中存储每个节点的前缀路径和,注意要加入0对应的值,使用dfs遍历树的每个节点,在遍历过程中,ans直接加上当前节点的路径和减去targetSum的键对应的值,因为这里定义的是具有默认值的字典,然后存储当前路径和,再递归遍历左子树和右子树,恢复现场继续遍历当前节点父节点的右子树。
法二:dfs
560.和为k的子数组(和437题一样)
前缀和加哈希表:哈希表中存储每个元素的前缀和,在遍历数组时,计算每个元素的前缀和并存储到哈希表中,并在哈希表中查询当前前缀和减去k是否在哈希表中,如果在,说明存在和为k的子数组
17.电话号码的字母组合
回溯:dfs函数的参数值是遍历到digits的第几个数字,也就是第几个按键,如果递归到了第i个按键,就遍历该按键所包含的所有字母,再递归遍历下一个按键,再恢复现场。
41.缺失的第一个正数
原地哈希:很神奇的思路...遍历数组中元素,如果这个数在1到n(数组长度)之间,并且不和待交换位置元素相等,则交换该位置元素和该数字减一对应的下标的元素,再遍历一次数组,如果该位置的元素值不等于下标值加一,则返回下标值加一,如果都满足条件,则返回n+1,注意不能.nums[i], nums[nums[i] - 1] = nums[nums[i] - 1], nums[i],会改变nums[i]的值
39.组合总和
回溯:组合问题,需要有st避免出现重复的情况,可以重复取元素,因此在进入下一层递归时,仍然是从第i个位置开始取元素,st为i,在最后收获结果的时候,要将path的拷贝加入到ans中