题20:表示数值的字符串
我的做法更复杂一点,因为之前没有考虑到科学计数法前半部分也可以是浮点数。主要是分情况讨论,分别处理:1)含有e时;2)不含e但含有.时3)既不含e也不含.时;这三种情况。同时,将有符号数和无符号数的判断集成为了函数;
class Solution:
def isNumber(self, s: str) -> bool:
s = s.strip() #去掉字符串的首尾空格
if s != '' and (s[0] == '+' or s[0] == '-'):#先处理首次出现的符号(其实也可以不处理)
s = s[1:]
def isUnsigned(sub: str) -> bool:#判断sub是否为无符号整数
if len(sub)==0:
return False
for i in sub:
if i not in ['0','1','2','3','4','5','6','7','8','9']:
return False
return True
def isSigned(sub: str) -> bool:#判断sub是否为有符号整数
if len(sub)==0:
return False
return (sub[0]=='+' or sub[0]=='-') and isUnsigned(sub[1:])
ind = max(s.find('e'),s.find('E'))#寻找s中是否存在e,若存在,则返回e所在下标,否则返回-1
if ind == -1: #不存在e
ind = s.find('.')#不存在e时,再判断是否存在.
if ind == -1: #若不存在.
return (isUnsigned(s) or isSigned(s))#判断是否为整数
else:#存在.,分为两段,对前后两段分别判断,注意,两段中可有一段为空
suba = s[:ind]
subb = '' if ind == len(s)-1 else s[ind+1:]
if suba == '' and subb == '':
return False
elif suba == '':
return isUnsigned(subb)
elif subb == '':
return (isUnsigned(suba) or isSigned(suba))
else:
return ((isUnsigned(suba) or isSigned(suba)) and isUnsigned(subb))
else:#存在e
suba = s[:ind]
subb = '' if ind == len(s)-1 else s[ind+1:]
if suba == '' or subb == '':
return False
else:
ind = suba.find('.')
if ind == -1:
return ((isUnsigned(suba) or isSigned(suba)) and (isUnsigned(subb) or isSigned(subb)))
else:
if isSigned(subb) or isUnsigned(subb):
saa = suba[:ind]
sab = '' if ind == len(suba)-1 else suba[ind+1:]
if saa == '' and sab == '':
return False
else:
return ((saa == '' or isUnsigned(saa)) and (sab == '' or isUnsigned(sab)))
else:
return False
更简单的做法:只以e为分隔符,分前后两段,然后对每一段进行逐个字符的判断,利用两个flag(havedot、havenum)去判断是否出现重复逗点等情况,👉题解链接
class Solution:
def isNumber(self, s: str) -> bool:
#处理多余空格
s=s.strip()
#分隔字符
pre,pst='',''
ind = s.find('e')
pre = s[:ind] if ind!=-1 else ''
pst = '' if ind == len(s)-1 else s[ind+1:]
# 数字部分
if len(pre) == 0:
return False
havedot ,havenum=False,False
for i in range(len(pre)):
if pre[i]=='+' or pre[i]== '-':
if i!=0:
return False
elif pre[i]=='.' :
if not havedot:
havedot =True
else :
return False
elif '0'<=pre[i]<='9':
havenum =True
else :
return False
if not havenum :
return False
# 指数部分
if pre != s and len(pst)==0:
return False
havenum = False
for i in range(len(pst)):
if pst[i] == '-' or pst[i] == '+':
if i != 0:
return False
elif pst[i]=='.':
return False
elif '0'<=pst[i]<='9':
havenum = True
else :
return False
if not havenum and len(pst)>0:
return False
return True
题21:调整数组顺序使奇数位于偶数前面
法一:暴力遍历
class Solution:
def exchange(self, nums: List[int]) -> List[int]:
even,odd = [],[]
for i in nums:
if i%2==0:
even.append(i)
else:
odd.append(i)
return odd+even
法二:双指针👉详细题解
head指针从首部开始查,直到遇到偶数停下;end指针从尾部向前查,直到遇到奇数停下;如果head>=end,则结束,否则,交换两个指针在nums中对应的数值
class Solution:
def exchange(self, nums: List[int]) -> List[int]:
head,end =0, len(nums)-1
while head<end:
while nums[head]%2==1 and head<end:
head+=1
while nums[end]%2==0 and end>head:
end-=1
if head>=end: #注意这一步判断!
break
nums[head],nums[end] = nums[end],nums[head]
return nums
题22:链表中倒数第k个节点
法一:暴力遍历
class Solution:
def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
# 思路:一次遍历记录下所有点,再切片【毫无技术含量
l=[]
while head!=None:
l.append(head)
head=head.next
llen = len(l)
if k>llen:
return None
return l[-k]
法二:快慢指针
class Solution:
def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
#正解:快慢指针
fast=head
low=head
i=0
while fast!=None:
print(fast.val)
fast=fast.next
i+=1
if(i>k):
low=low.next
return low
题24:反转链表
链表基本操作,但需要想清楚需要几个指针
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
pre=None
cur=head
while cur!=None:
tmp=cur.next
cur.next=pre
pre=cur
cur=tmp
return pre
题25:合并两个排序的链表
法一:不创造新的空间,直接插入,注意,需要创造一个头节点来处理头部插入
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
if l1 == None:
return l2
elif l2 == None:
return l1
head = ListNode(-1)
head.next = l1
s1,s2 = head,l1
p1,p2 = l2,l2.next
while s2!=None and p1!=None:
if p1.val <= s2.val:
s1.next = p1
p1.next = s2
s1 = p1
p1 = p2
if p2 == None:
break
else:
p2 = p2.next
else:
s1 = s2
s2 = s2.next
if p1!=None:
s1.next = p1
return head.next
法二:创造新的空间,这样更简单,不需要过多的指针操作
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
cur = dum = ListNode(0)
while l1 and l2:
if l1.val < l2.val:
cur.next, l1 = l1, l1.next
else:
cur.next, l2 = l2, l2.next
cur = cur.next
cur.next = l1 if l1 else l2
return dum.next
题26: 树的子结构
借鉴王先生的题解:两个递归,一个递归实现深度遍历A,另一个递归实现判断是否满足子结构,很巧妙
利用isSubStructure函数实现对A的遍历,judge函数用户判断当前的A是否包含B这个子结构。
子结构判断:如果B走到了空,则说明匹配了;如果A走到了空或者A的值和B的值不相等,说明不匹配;否则接着判断;
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool:
def judge(A,B):
if B == None:
return True
if A == None or A.val != B.val:
return False
return judge(A.left,B.left) and judge(A.right,B.right)
return bool(A and B) and (judge(A,B) or isSubStructure(A.left,B) or isSubStructure(A.right,B))
题27: 二叉树的镜像
凭直觉写出来的递归,比某人的要简洁哈哈哈哈
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def mirrorTree(self, root: TreeNode) -> TreeNode:
if root!=None:
root.right,root.left=self.mirrorTree(root.left),self.mirrorTree(root.right)
return root
题28: 对称的二叉树
借鉴了王先生的题解:
判断二叉树是否镜像对称:
左子树的左子树等于右子树的右子树
左子树的右子树等于右子树的左子树
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
if root == None:
return True
def judge(r1,r2):
if r1 == None and r2 == None:
return True
elif r1 == None or r2 == None:
return False
else:
return judge(r1.right,r2.left) and judge(r1.left,r2.right) if r1.val == r2.val else False
return judge(root.right,root.left)
题29:
自己想的:以剥离矩阵最外层一圈为单位,重复剥离即可。
设置四个指针:sti指向该剥离的上边缘的行指标,edi表示该剥离的下边缘的行指标,stj表示该剥离的左边缘的列指标,edj表示该剥离的右边缘的列指标。每剥离一次,四个指标向内收缩。
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
if len(matrix)==0 or len(matrix[0])==0:
return matrix
n,m=len(matrix),len(matrix[0])
nmmin=min(n,m)
if nmmin%2==0:
cir = int(nmmin/2)
else:
cir=int(nmmin/2+1)
sti,edi,stj,edj = 0,n-1,0,m-1
res=[]
for ind in range(cir):
if stj==edj:
for i in range(sti,edi+1):
res.append(matrix[i][edj])
elif sti==edi:
for j in range(stj,edj+1):
res.append(matrix[sti][j])
else:
for j in range(stj,edj+1):
res.append(matrix[sti][j])
for i in range(sti+1,edi+1):
res.append(matrix[i][edj])
for j in range(edj-1,stj-1,-1):
res.append(matrix[edi][j])
for i in range(edi-1,sti,-1):
res.append(matrix[i][stj])
sti+=1
edi-=1
stj+=1
edj-=1
return res
题30:包含min函数的栈
借鉴王先生的题解:
用minst栈来存储前i个数中的最小值,妙
class MinStack:
def __init__(self):
self.stack = []
self.minst = []
def push(self, x: int) -> None:
self.stack.append(x)
if len(self.minst)>0:
self.minst.append(x if x<self.minst[-1] else self.minst[-1])
else:
self.minst.append(x)
def pop(self) -> None:
self.stack.pop()
self.minst.pop()
def top(self) -> int:
return self.stack[-1]
def min(self) -> int:
if len(self.stack)==0:
return null
else:
return self.minst[-1]
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.min()
题31:栈的压入、弹出顺序
自己能想到规律,但做不到清晰地整理出来,参考了王先生的题解,相形见绌:
将pushed和popped中的元素从第一个开始逐个比较,分三种情况:
1、两者相同(说明该元素刚入栈就被弹出),继续向下匹配
2、两者不同,再判断出栈元素是否为当前栈中的第一个元素,若相同,将栈中第一个元素弹出,继续向下匹配;
3、若不符合上述两种情况,则说明该模式不合理;
!!仔细看代码
class Solution:
def validateStackSequences(self, pushed: List[int], popped: List[int]) -> bool:
n, m = len(pushed), len(popped)
if m!=n:
return False
i, j, stack = 0, 0, []
while j<m:
if i<n and pushed[i]==popped[j]:
i+=1
j+=1
elif len(stack)>0 and popped[j]==stack[-1]:
j+=1
stack.pop()
else:
if i<n:
stack.append(pushed[i])
i+=1
if i>=n:
break
return True if j==m else False
题32-1:从上到下打印二叉树
队列的应用
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def levelOrder(self, root: TreeNode) -> List[int]:
queue,res = [],[]
if root!=None:
queue.append(root)
else:
return res
while queue!=[]:
tmp = queue.pop(0)
res.append(tmp.val)
if tmp.left!=None:
queue.append(tmp.left)
if tmp.right!=None:
queue.append(tmp.right)
return res
题32-2:从上到下打印二叉树
多一个index列表,用于存储每个元素所在行数
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
queue,index,res = [],[],[]
if root!=None:
queue.append(root)
index.append(0)
else:
return res
while len(queue)!=0:
tmp = queue.pop(0)
ind = index.pop(0)
if len(res)==ind:
res.append([])
res[ind].append(tmp.val)
if tmp.left!=None:
queue.append(tmp.left)
index.append(ind+1)
if tmp.right!=None:
queue.append(tmp.right)
index.append(ind+1)
return res
题32-3:从上到下打印二叉树
偶数行倒序输出即可,这是最简单的方法
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
queue,index,res = [],[],[]
if root!=None:
queue.append(root)
index.append(0)
else:
return res
while len(queue)!=0:
tmp = queue.pop(0)
ind = index.pop(0)
if len(res)==ind:
res.append([])
res[ind].append(tmp.val)
if tmp.left!=None:
queue.append(tmp.left)
index.append(ind+1)
if tmp.right!=None:
queue.append(tmp.right)
index.append(ind+1)
for i in range(len(res)):
if i%2==1:
res[i]=res[i][::-1]
return res
题33:二叉搜索树的后序遍历序列
二叉搜索树的特点:左子树全部小于根节点,右子树全部大于根节点。那么所给序列必须满足这一特点。【自己想的,时间复杂度应该不是最优】
class Solution:
def verifyPostorder(self, postorder: List[int]) -> bool:
flag = 1
def judge(plist):
nonlocal flag
if len(plist)>1:
root,pre,pst = plist[-1],[],[]
#找出左右子树的分裂点
for i in range(len(plist)-1):
if plist[i]>root:
break
#处理右子树为空的情况
if i == len(plist)-2:
i+=1
pre = plist[:i]
pst = plist[i:-1]
#判断右子树是否满足条件
if len(pst)!=0:
for i in pst:
if i<root:
flag = 0
#print(plist,pre,pst,flag,root)
#递归判断
judge(pre)
judge(pst)
judge(postorder)
return True if flag ==1 else False