目录
51.构建乘积数组
给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素
B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法。
先求前向乘积列表t_forword=a[0]*a[1]*...*a[i-1];存入b
再求后项乘积列表t_back=a[len(a)-1]*a[len(a)-1]*...*a[i+1];b[i]*t_back得到最后结果
class Solution:
def multiplyArr(self,a):
b=[1]*len(a)
#前向乘积a[0]*a[1]...a[i-1]
t_forward=1
for i in range(1,len(a),1):
t_forward*=a[i-1]
b[i]=t_forward
#后项乘积获取a[len(a)-1]*a[len(a)-1]*...*a[i+1]
t_back=1
for i in range(len(a)-1,-1,-1):
b[i]*=t_back
t_back*=a[i]
return b
def valid(self,a):
t=1
b=[]
for i in a:
t*=i
for i in a:
b.append(t/i)
return b
s=Solution()
a=[1,2,3,4,5]
r1=s.multiplyArr(a)
r2=s.valid(a)
print(r1,r2)
52.正则表达式匹配
请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,
而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配
整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配。
思路:递归匹配f(s,p),s字符串,p模式
1、当p的第二个字符p[1]不是*时:(1)如果s[0]与p[0]相匹配,那么s和p均后移一位,匹配剩余的f(s-1,p-1);
(2)如果字符串第一个字符和模式中的第一个字符相不匹配,直接返回false。
2、当p的第二个字符p[1]是*时:如果s[0]与p[0]相匹配:
(1)字符串后移1位,模式后移2字符。
(2)字符串后移1位,模式不变,相当于x*中的x出现多次;
如果s[0]与p[0]不匹配:字符串不变,模式后移2字符,相当于x*中的x出现0次;
3、当s和p均为0时,匹配成功返回;如果其中一个不为0,匹配失败
class Solution:
def match(self,s,p):
if len(s)==0 and len(p)==0:
return True
if (len(s)!=0 and len(p)==0) or (len(s)==0 and len(p)!=0):
return False
if len(p)>1 and p[1]=='*':
if (p[0]==s[0] or p[0]=='.'):
return self.match(s[1:],p[2:]) or self.match(s[1:],p)
else:
return self.match(s,p[2:])
else:
if (p[0]==s[0] or p[0]=='.'):
return self.match(s[1:],p[1:])
else:
return False
a="aaab"
p="ab*ac*a"
s=Solution()
r=s.match(a,p)
print(r)
53.表示数值的字符串
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123",
"3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。
思路:重点需要考察的是
1)是否有符号;符号只可能出现在开头和eE的后面
2)是否有. ; .只能出现一次,不能在eE附近,不能在eE后面,且前后必须为数字
3)是否有eE; e或E只能出现一次且不能在开头和末尾,前面只能是数字,后面只能是"+-0123456789"
4)是否在"0123456789"之间
class Solution:
def isNumStr(self,s):
hasDot=True
hasE=True
for i in range(len(s)):
if(s[i] in "+-" and (i==0 or (i<=len(s)-1 and s[i-1] in "Ee") ) ):
continue
elif hasDot and s[i]=='.':
hasDot=False
if i>=len(s)-1 or s[i+1] not in "0123456789":
return False
elif hasE and s[i] in 'eE':
hasDot=False
hasE=False
if (i==0 or i>=len(s)-1) or (s[i-1] not in "0123456789") or (s[i+1] not in "+-0123456789"):
return False
elif s[i] not in "0123456789":
return False
return True
s=Solution()
r=s.isNumStr("-123.123e-10")
print(r)
54.字符流中第一个不重复的字符
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,
第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
思路:声明一个字典记录每个字符出现的次数,遍历字符串,如果第一次出现次数为1的,则返回
class Solution:
def findAppearOnce(self,s):
char_num={}
for c in s:
if c not in char_num.keys():
char_num[c]=1
else:
char_num[c]+=1
for c in s:
if char_num[c]==1:
return c
return None
s=Solution()
r=s.findappearOnce("google")
print(r)
55.链表中环的入口节点
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
思路:快慢指针,快指针走两步,慢指针走一步;当快指针fast与low指针相遇时,及找到了循环链表的入口
class Node:
def __init__(self,val):
self.val=val
self.next=None
class Solution:
def findEntryNodeOfLoop(self,head):
if head ==None or head.next==None or head.next.next==None:
return None
fast=head.next.next
low=head.next
while fast and low:
if fast==low:
return fast
if fast.next==None or fast.next.next==None:
return None
fast=fast.next.next
low=low.next
return None
56.删除链表中重复的结点
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。
例如,链表1->2->3->3->4->4->5 处理后为 1->2->5。(leetcode82)
思路:1、因为是排序链表,重复的数都是挨着的,遍历一遍链表删除重复的数据
class Node:
def __init__(self,val):
self.val=val
self.next=None
class Solution:
def deleteDuplicatedNode(self,head):
dupli=Node(-1) #避免第一个节点就是重复节点
dupli.next=head
cur=head
last=dupli
while cur and cur.next:
if cur.val==cur.next.val:
val=cur.val
while cur and val==cur.val:
cur=cur.next
last.next=cur
else:
last=cur
cur=cur.next
return dupli.next
a = Node(1)
b = Node(2)
c = Node(2)
d = Node(5)
e = Node(6)
f = Node(6)
a.next = b
b.next = c
c.next = d
d.next = e
e.next = f
s=Solution()
res = s.deleteDuplicatedNode(a)
cur = res
while cur:
print(cur.val)
cur = cur.next
57.二叉树的下一个结点
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包
含左右子结点,同时包含指向父结点的指针。
给定二叉树:
3
/ \
9 20
/ \
15 7
思路:
1、如果该节点有右子树,那么它的下一个节点就是它的右子树的最左侧子节点;
2、如果该节点没有右子树且是父节点的左子树,那么下一节点就是父节点;
3、如果该节点没有右子树且是父节点的右子树,比如i节点,那么我们往上找父节点,找到一个节点满足:
它是它的父节点的左子树的节点。
class TreeNode:
def __init__(self,val):
self.val=val
self.left=None
self.right=None
self.parent=None
class Solution:
def findNext(self,root,p):
if root==None:
return None
if p.right:
res=p.right
while res.left:
res=res.left
else:
while p.parent:
res=p.parent
if res.left==p:
return res
p=p.parent
return res
a = TreeNode(3)
b = TreeNode(9)
d = TreeNode(20)
e = TreeNode(15)
f = TreeNode(7)
a.left, a.right = b, d
b.parent,d.parent=a,a
d.left, d.right = e,f
e.parent,f.parent=d,d
s=Solution()
res = s.findNext(a,b)
print(res.val)
58.对称的二叉树
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,
定义其为对称的。如下二叉树即为对称二叉树
1
/ \
2 2
/ \ / \
3 4 4 3
思路:递归地判断左右子树是否对称;递归结束条件,左右子树都为空,返回True,仅仅left或right为空
或左右子树的值不相等,返回False
class TreeNode:
def __init__(self,val):
self.val=val
self.left=None
self.right=None
class Solution:
def isSymmertrical(self,root):
if root==None:
return True
return self.ismirror(root.left,root.right)
def ismirror(self,left,right):
if left==None and right==None:
return True
if left==None or right==None or left.val!=right.val:
return False
return self.ismirror(left.left,right.right) and self.ismirror(left.right,right.left)
a = TreeNode(3)
b = TreeNode(9)
d = TreeNode(20)
e = TreeNode(15)
f = TreeNode(7)
a.left, a.right = b, d
d.left, d.right = e,f
s=Solution()
res = s.isSymmertrical(a)
print(res)
59.把二叉树打印成多行
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。(leetcode102题)
给定二叉树:
3
/ \
9 20
/ / \
6 15 7
返回其层次遍历结果:
[
[3],
[9,20],
[6,15,7]
]
思路:层次遍历二叉树;1、申请一队列q,存储当前层次节点;2、循环遍历队列q,pop开头节点cur,并
将cur.val结果存入列表t;3、将每层结果列表t存入最终结果res,循环2直到q为空
class TreeNode:
def __init__(self,val):
self.val=val
self.left=None
self.right=None
class Solution:
def printTreeRow(self,root):
q=[root]
res=[]
while q:
t=[]
cur_level_nodes=len(q)
for i in range(cur_level_nodes):
cur=q.pop(0)
t.append(cur.val)
if cur.left:
q.append(cur.left)
if cur.right:
q.append(cur.right)
res.append(t)
return res
a = TreeNode(3)
b = TreeNode(9)
c=TreeNode(6)
d = TreeNode(20)
e = TreeNode(15)
f = TreeNode(7)
a.left, a.right = b, d
d.left, d.right = e,f
b.left=c
s=Solution()
res = s.printTreeRow(a)
print(res)
60.按之字形顺序打印二叉树
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,
第三行按照从左到右的顺序打印,其他行以此类推。
给定二叉树:
3
/ \
9 20
/ / \
6 15 7
返回其层次遍历结果:
[
[3],
[20,9],
[6,15,7]
]
思路:层次遍历二叉树;1、申请一队列q,存储当前层次节点;2、循环遍历队列q,pop开头节点cur,并
将cur.val结果存入列表t; 3、如果是单行将每层结果列表t存入res,如果是双行,将t的反转存到res,
循环2直到q为空
class TreeNode:
def __init__(self,val):
self.val=val
self.left=None
self.right=None
class Solution:
def printTreeRowZ(self,root):
q=[root]
res=[]
flag=True #标识单层还是双层
while q:
t=[]
cur_level_nodes=len(q)
for i in range(cur_level_nodes):
cur=q.pop(0)
t.append(cur.val)
if cur.left:
q.append(cur.left)
if cur.right:
q.append(cur.right)
if flag:
res.append(t)
flag=False
else:
res.append(t[::-1])
flag=True
return res
a = TreeNode(3)
b = TreeNode(9)
c=TreeNode(6)
d = TreeNode(20)
e = TreeNode(15)
f = TreeNode(7)
a.left, a.right = b, d
d.left, d.right = e,f
b.left=c
s=Solution()
res = s.printTreeRowZ(a)
print(res)