1171 从链表中删去总和值为零的连续节点
前缀和 用字典 前缀和存指针
两个结点的前缀和相等,说明两个结点之间和为0、
如果后面前缀和等于前面的前缀和,则用后面的结点覆盖前面的结点
然后重构结点
申请当前节点的前缀和sum为key,当前节点指针为value的哈希表
class Solution:
def removeZeroSumSublists(self, head: ListNode) -> ListNode:
seen=dict()
dummy=ListNode(0)
dummy.next=head
cur=head
seen[0]=dummy
pre=0
while cur:
pre+=cur.val
seen[pre]=cur
cur=cur.next
pre=0
cur=dummy
while cur:
pre+=cur.val
cur.next=seen[pre].next
cur=cur.next
return dummy.next
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
slow,fast=head,head
while fast and fast.next:
slow,fast=slow.next,fast.next.next
if slow==fast:
break
if not fast or not fast.next:
return None
pre=head
while pre!=fast:
pre,fast=pre.next,fast.next
return pre
面试题06. 从尾到头打印链表
最简单的把链表数据读入列表,然后翻转列表
递归法:先走至链表末端,回溯时依次将节点值加入列表 ,这样就可以实现链表值的倒序输出
class Solution:
def reversePrint(self, head: ListNode) -> List[int]:
return self.reversePrint(head.next) + [head.val] if head else []
面试题36. 二叉搜索树与双向链表 同426
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。
“head” 表示指向链表中有最小元素的节点。
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
def dfs(cur):
if not cur:
return
dfs(cur.left)
if self.pre:
#右指针指向后继节点,左指针指向前驱节点
self.pre.right,cur.left=cur,self.pre
else:
#左叶子节点是头结点
self.head=cur
self.pre=cur
dfs(cur.right)
if not root:
return
self.pre=None
dfs(root)
#头结点的前驱是尾节点,尾节点的后继是头结点
self.head.left,self.pre.right=self.pre,self.head
return self.head
10. 正则表达式匹配
如果没有星号(正则表达式中的 * ),问题会很简单——我们只需要从左到右检查匹配串 s 是否能匹配模式串 p 的每一个字符。
当模式串中有星号时,我们需要检查匹配串 s 中的不同后缀,以判断它们是否能匹配模式串剩余的部分
如果模式串p中有星号,它会出现在第二个位置,即pattern[1] 。这种情况下,我们可以直接忽略模式串中这一部分,或者删除匹配串s的第一个字符,前提是它能够匹配模式串当前位置字符,即 pattern[0] 。如果两种操作中有任何一种使得剩下的字符串能匹配,那么初始时,匹配串和模式串就可以被匹配。
class Solution:
def isMatch(self, s: str, p: str) -> bool:
if not p:
return not s
#下一位为‘*’时,如果第一位不匹配,则直接判断s 和p[2:]是否匹配,因为‘*’前面一位可以出现0次
#如果第一位匹配或者为'.'(匹配任意字符),则判断s[1:] 和p(实例2),s,p[2:](实例4)是否匹配
if len(p)>1 and p[1]=='*':
if s and (p[0]=='.' or s[0]==p[0]) :
return self.isMatch(s,p[2:]) or self.isMatch(s[1:],p)
#如果第一位不匹配,跳过p的前两位,从p[2:]开始继续判断是否与s匹配
return self.isMatch(s,p[2:])
#第一项匹配且第二位不是‘*’,则按位判断
if s and (p[0]==s[0] or p[0]=='.'):
return self.isMatch(s[1:],p[1:])
return False
class Solution:
#将多个连续*用一个*替代
def remove_stars(self,p):
if p=='':
return p
p1=[p[0]]
for x in p[1:]:
if p1[-1]!='*' or p1[-1]=='*' and x!='*':
p1.append(x)
return ''.join(p1)
def helper(self,s,p):
dp=self.dp
if (s,p) in dp:
return dp[(s,p)]
if s==p or p=='*':
dp[(s,p)]=True
elif not s or not p:
dp[(s,p)]=False
elif s[0]==p[0] or p[0]=='?':
dp[(s,p)]=self.helper(s[1:],p[1:])
elif p[0]=='*':
#不匹配字符或者匹配一个到多个
dp[(s,p)]=self.helper(s,p[1:]) or self.helper(s[1:],p)
else:
dp[(s,p)]=False
return dp[(s,p)]
def isMatch(self, s: str, p: str) -> bool:
p=self.remove_stars(p)
#构建哈希表存储已经检查过的(s,p)
self.dp={}
return self.helper(s,p)
面试题04:二维数组中的查找 同240. 搜索二维矩阵 II
左下角元素 为所在列最大元素,所在行最小元素
如果 左下角元素 大于了目标值,则目标值一定在该行的上方, 左下角元素所在行可以消去。
如果 左下角元素 小于了目标值,则目标值一定在该列的右方, 左下角元素所在列可以消去。
class Solution:
def searchMatrix(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: bool
"""
i,j=len(matrix)-1,0
while i>=0 and j<len(matrix[0]):
if matrix[i][j]==target:
return True
elif matrix[i][j]>target:
i-=1
elif matrix[i][j]<target:
j+=1
return False
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
i,j=len(matrix)-1,0
while i>=0 and j<len(matrix[0]):
if matrix[i][j]==target:
return True
elif matrix[i][j]<target:
j+=1
elif matrix[i][j]>target:
i-=1
return False
二分查找:
输入的 m x n 矩阵可以视为长度为 m x n的有序数组。
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
m=len(matrix)
if m==0:
return False
n=len(matrix[0])
#二分查找
left,right=0,m*n-1
while left<=right:
pivort=(right+left)//2
pivort_e=matrix[pivort//n][pivort%n]
if pivort_e==target:
return True
elif pivort_e>target:
right=pivort-1
else:
left=pivort+1
return False
class Solution:
def firstUniqChar(self, s: str) -> int:
mark=defaultdict(int)
for i in range(len(s)):
mark[s[i]]+=1
p=None
for i,v in mark.items():
if v==1:
p=i
break
for c in range(len(s)):
if p==s[c]:
return c
return -1
class Solution:
def decodeString(self, s: str) -> str:
res,stack,n='',[],0
for c in s:
if c=='[':
#将当前res和倍数入栈,并将其重置为0,用于保存[]内的数据
stack.append([res,n])
res=''
n=0
#字符串的数字要挨个位置叠加
elif c.isdigit():
n=n*10+int(c)
elif c==']':
last_res,cur_n=stack.pop()
res=last_res+cur_n*res
else:
res+=c
return res