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]。不能使用除法。
思路:
B[0] = A[1] * A[2] * A[3] * A[4] *....*A[n-1] ;(没有A[0])
B[1 ]= A[0] * A[2] * A[3] * A[4] *....*A[n-1] ;(没有A[1])
B[2] = A[0] * A[1] * A[3] * A[4] *....*A[n-1] ;(没有A[2])
class Solution:
def multiply(self, A):
# write code here
B = A[:]
for m in range(len(A)):
sum = 1
for n in range(len(A)):
if n != m:
sum = sum*A[n]
B[m] = sum
return B
52.请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配
思路:
当模式中的第二个字符不是“*”时:
1、如果字符串第一个字符和模式中的第一个字符相匹配,那么字符串和模式都后移一个字符,然后匹配剩余的。
2、如果 字符串第一个字符和模式中的第一个字符相不匹配,直接返回false。
而当模式中的第二个字符是“*”时:
如果字符串第一个字符跟模式第一个字符不匹配,则模式后移2个字符,继续匹配。如果字符串第一个字符跟模式第一个字符匹配,可以有3种匹配方式:
1、模式后移2字符,相当于x*被忽略;
2、字符串后移1字符,模式后移2字符;
3、字符串后移1字符,模式不变,即继续匹配字符下一位,因为*可以匹配多位;
# -*- coding:utf-8 -*-
class Solution:
# s, pattern都是字符串
def match(self, s, pattern):
# write code here
if (len(s) == 0 and len(pattern) == 0):
return True
if (len(s) > 0 and len(pattern) == 0):
return False
if (len(pattern) > 1 and pattern[1] == '*'):
if (len(s) > 0 and (s[0] == pattern[0] or pattern[0] == '.')):
return (self.match(s, pattern[2:]) or self.match(s[1:], pattern[2:]) or self.match(s[1:], pattern))
else:
return self.match(s, pattern[2:])
if (len(s) > 0 and (pattern[0] == '.' or pattern[0] == s[0])):
return self.match(s[1:], pattern[1:])
return False
53.请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。
方法1:笔试做法。
class Solution:
# s字符串
def isNumeric(self, s):
# write code here
try:
L = float(s)
return True
except:
return False
方法2:循环判断,思路:
12e
说明e的后面必须有数字,不能有两个e+-5
说明符号位要么出现一次在首位,要么出现一次在e的后一位,其他地方都不能有12e4.3
说明e的后面不能有小数,1.2.3
说明不能有两个小数点1a3.14
说明不能有其他的非法字符,比如这里的a
# -*- coding:utf-8 -*-
class Solution:
# s字符串
def isNumeric(self, s):
# write code here
n = len(s)
if n==0:
return False
type = 0
for i in range(n):
#print s[i]
if s[i]=="+" or s[i]=="-":
if i==n-1:#正负号后面没数字了
return False
elif i==0:
type = 1#整型
elif type==3:
continue
else:
return False
elif s[i]=="E" or s[i]=="e":
if (type==1 or type==2) and i!=n-1:#E/e后面不能没有数字
type = 3
else:
return False
elif s[i]==".":
if type==1 or type==0 and i!=n-1:
type = 2
else:
return False
elif "0"<=s[i]<="9":
if i==0:
type=1
continue
else:
return False
return True
54.请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。如果没有,则输出"#"。
# -*- coding:utf-8 -*-
class Solution:
# 返回对应char
def __init__(self):
self.s = ''
self.dict = {}
def FirstAppearingOnce(self):
# write code here
for i in self.s:
if self.dict[i] == 1:
return i
return '#'
def Insert(self, char):
# write code here
self.s += char
if char in self.dict:
self.dict[char] += 1
else:
self.dict[char] = 1
55.给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
思路:遍历链表,环的存在,遍历遇见的第一个重复的即为入口节点。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def EntryNodeOfLoop(self, pHead):
# write code here
temp = []
p = pHead
while p:
if p in temp:
return p
else:
temp.append(p)
p = p.next
56.在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5.
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def deleteDuplication(self, pHead):
# write code here
if pHead is None or pHead.next is None:
return pHead
head1 = pHead.next
if head1.val != pHead.val:
pHead.next = self.deleteDuplication(pHead.next)
else:
while head1.val == pHead.val and head1.next is not None:
head1 = head1.next
if head1.val != pHead.val:
#注意此处是pHead而不是pHead1,目的是删除重复出现的结点,一个不留
pHead = self.deleteDuplication(head1)
else:
return None
return pHead
57.给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
思路:二叉树的中序遍历为左根右,方式为递归。若要找下一个结点,有三种情况。
1.二叉树为空,则返回空;
2.节点右孩子存在,则设置一个指针从该节点的右孩子出发,一直沿着指向左子结点的指针找到的叶子节点即为下一个节点;
3.节点不是根节点。如果该节点是其父节点的左孩子,则返回父节点;否则继续向上遍历其父节点的父节点,重复之前的判断,返回结果。
-*- coding:utf-8 -*-
class TreeLinkNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
self.next = None
class Solution:
def GetNext(self, pNode):
# write code here
if not pNode:
return pNode
if pNode.right:
left1 = pNode.right
while left1.left:
left1 = left1.left
return left1
else:
while pNode.next:
temp = pNode.next
if temp.left == pNode:
return temp
pNode = temp
58.请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isSymmetrical(self, pRoot):
# write code here
def is_Same(p1, p2):
if not p1 and not p2:
return True
if p1 and p2:
if p1.val==p2.val:
return is_Same(p1.left, p2.right) and is_Same(p1.right, p2.left)
return False
return False
if not pRoot:
return True
if pRoot.left and not pRoot.right:
return False
if pRoot.right and not pRoot.left:
return False
return is_Same(pRoot.left, pRoot.right)
59.请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
#利用双队列实现
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
from collections import deque
class Solution:
def Print(self, pRoot):
if not pRoot:
return []
result = []
tmp = []
last = pRoot #记录每层的最后一个结点,方便层序遍历换行
left_to_right = True
next_level_node_LtoR = deque([pRoot]) #初始化下一层所有节点的队列,起初为只有根结点
while next_level_node_LtoR: #当下一层不为空时
current_node = next_level_node_LtoR.popleft() #不停从下层队列左边弹出
tmp.append(current_node.val) #将弹出结点放入tmp中
if current_node.left:
next_level_node_LtoR.append(current_node.left)
if current_node.right:
next_level_node_LtoR.append(current_node.right)
if current_node == last: #当运行到最后一个结点,给result赋值当前行的所有元素,也就是tmp
if left_to_right:
result.append(tmp)
else: #若该行应该为从右到左,则倒序append
result.append(tmp[::-1])
tmp = [] #清空tmp,以便下一层继续使用
left_to_right = not left_to_right #调整此项,颠倒下一行的输出顺序
if next_level_node_LtoR: #更新下一行的last结点,如果下一行已经没有元素就会退出
last = next_level_node_LtoR[-1]
return result
60.从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
思路:
按层次输出二叉树
* 访问根节点,并将根节点入队。
* 当队列不空的时候,重复以下操作。
* 1、弹出一个元素。作为当前的根节点。
* 2、如果根节点有左孩子,访问左孩子,并将左孩子入队。
* 3、如果根节点有右孩子,访问右孩子,并将右孩子入队。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回二维列表[[1,2],[4,5]]
def Print(self, pRoot):
# write code here
if not pRoot:
return []
nodestack = [pRoot]
result = []
while nodestack:
res = []
nextstack = []
for i in nodestack:
res.append(i.val)
if i.left:
nextstack.append(i.left)
if i.right:
nextstack.append(i.right)
nodestack = nextstack
result.append(res)
return result
61.请实现两个函数,分别用来序列化和反序列化二叉树
分析:
1.序列化是指通过前序遍历把二叉树变成数组
2.反序列化是指重建二叉树
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
flag = -1
def Serialize(self, root):
# write code here
if not root:
return '#'
return str(root.val) + ',' + self.Serialize(root.left) + ',' + self.Serialize(root.right)
def Deserialize(self, s):
# write code here
self.flag += 1
l = s.split(',')
if self.flag >= len(s):
return None
root = None
if l[self.flag] != '#':
root = TreeNode(int(l[self.flag]))
root.left = self.Deserialize(s)
root.right = self.Deserialize(s)
return root
62.给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。
分析:对二叉搜索树中序遍历便能得到排序数组,然后按顺序输出数组中的第k个数即可。
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def KthNode(self, pRoot, k):
if not pRoot or k == 0:
return None
n = self.isorder(pRoot)
if k > len(n):
return None
return n[k-1]
def isorder(self, pRoot):
res = []
if not pRoot:
return None
if pRoot.left:
res.extend(self.isorder(pRoot.left)) #注意列表里添加列表用extend
res.append(pRoot) #列表里添加元素用append
if pRoot.right:
res.extend(self.isorder(pRoot.right))
return res
63.如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.data = []
def Insert(self, num):
# write code here
self.data.append(num)
self.data.sort()
def GetMedian(self,data):
# write code here
l = len(self.data)
if l%2 == 0:
return (self.data[l//2]+self.data[l//2-1])/2.0
else:
return self.data[int(l//2)]
64.给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
# -*- coding:utf-8 -*-
class Solution:
def maxInWindows(self, num, size):
# write code here
if len(num) < size or size == 0:
return []
temp = []
for i in range(len(num)-size+1):
temp.append(max(num[i:i+size]))
return temp
65.请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。 例如 a b c e s f c s a d e e 这样的3 X 4 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
分析:这是回溯法的典型例子。
由于路径不能重复进入矩阵的格子,还需要定义和字符矩阵大小一样的布尔值矩阵,用来标识路径是否已经进入每个格子。 当矩阵中坐标为(row,col)的
格子和路径字符串中相应的字符一样时,从4个相邻的格子(row,col-1),(row-1,col),(row,col+1)以及(row+1,col)中去定位路径字符串中下一个字符。
如果4个相邻的格子都没有匹配字符串中下一个的字符,表明当前路径字符串中字符在矩阵中的定位不正确,我们需要回到前一个,然后重新定位。一直重复这个过程,直到路径字符串上所有字符都在矩阵中找到合适的位置。
class Solution:
def hasPath(self, matrix, rows, cols, path):
for i in range(rows):
for j in range(cols):
if matrix[i*cols+j] == path[0]:
if self.findPath(list(matrix), rows, cols, path[1:], i ,j)
return True
return False
def findPath(self, matrix, rows, cols, path , i, j):
if not path:
return True
matrix[i*cols+j] = '#' #将已经遍历的点作标记
if j+1<cols and matrix[i*cols+j+1]==path[0]:
return self.find(matrix,rows,cols,path[1:],i,j+1)
elif j-1>=0 and matrix[i*cols+j-1]==path[0]:
return self.find(matrix,rows,cols,path[1:],i,j-1)
elif i+1<rows and matrix[(i+1)*cols+j]==path[0]:
return self.find(matrix,rows,cols,path[1:],i+1,j)
elif i-1>=0 and matrix[(i-1)*cols+j]==path[0]:
return self.find(matrix,rows,cols,path[1:],i-1,j)
else:
return False
66.地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
思路:使用回溯法,将地图全部置1,遍历能够到达的点,将遍历的点置0并令计数+1.
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.count = 0
def movingCount(self, threshold, rows, cols):
# write code here
arr = [[1 for i in range(cols)] for j in range(rows)]
self.findway(arr, 0 ,0 ,threshold)
return self.count
def findway(self, arr, i, j, k):
if i<0 or j<0 or i>=len(arr) or j>=len(arr[0]):
return
tempi = list(map(int, list(str(i))))
tempj = list(map(int, list(str(j))))
if sum(tempi)+sum(tempj) >k or arr[i][j] != 1:
return
arr[i][j] = 0
self.count += 1
self.findway(arr, i+1, j ,k)
self.findway(arr, i - 1, j, k)
self.findway(arr, i, j + 1, k)
self.findway(arr, i, j - 1, k)