博客地址
https://blog.csdn.net/u012193416/article/details/79253398
1. 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
class Solution:
# array 二维列表
def Find(self, target, array):
# write code here
row = len(array)
col = len(array[0])
for i in range(row):
for j in range(col):
if target == array[i][j]:
return True
return False
方法二:上述方法的时间复杂度是O(n^2),最优化的方式是从左下或者右上开始搜索 从右上开始搜索,如果数组中的数比该数要大,那么想左移动一位,如果数组中的数比该数小,向下移动一位, 因为数组本身是从左到右依次增大,从上到下一次增大 。
class Solution:
# array 二维列表
def Find(self, target, array):
# write code here
row = len(array)
col = len(array[0])
i = 0
j = col - 1
while i < row and j >= 0:
if array[i][j] > target:
j -= 1
elif array[i][j] < target:
i += 1
else:
return True
return False
2.请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
class Solution:
# s 源字符串
def replaceSpace(self, s):
# write code here
return s.replace(' ','%20')
3.输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回从尾部到头部的列表值序列,例如[1,2,3]
def printListFromTailToHead(self, listNode):
# write code here
if not listNode:
return []
result = []
head = listNode
while head:
result.insert(0, head.val)
head = head.next
return result
4.输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
思路
-
1.创建根节点
-
2.根据前序遍历中第一个值(即为根节点的值)找到根节点在中序遍历中的位置pos
-
3.根据规律找到左子树和右子树所对应的前序遍历与中序遍历的列表范围,递归建树。
# -*- coding:utf-8 -*-
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
# 返回构造的TreeNode根节点
def reConstructBinaryTree(self, pre, tin):
# write code here
if not pre or not tin:
return None
root = TreeNode(pre[0])
val = tin.index(pre[0])
# 可以动手试一下啊,第一个参数
root.left = self.reConstructBinaryTree(pre[1:val + 1], tin[:val])
root.right = self.reConstructBinaryTree(pre[val + 1:], tin[val + 1:])
return root
下面的代码完成个二叉树的各种遍历
https://www.cnblogs.com/lliuye/p/9143676.html
#coding=utf-8
#二叉树节点
class TreeNode:
def __init__(self, val=None, left=None, right=None):
self.val = val
self.left = left
self.right = right
def PreOrder(root):
'''先序遍历'''
if root == None:
return
print(root.val)
PreOrder(root.left)
PreOrder(root.right)
def InOrder(root):
'''中序遍历'''
if root == None:
return
InOrder(root.left)
print(root.val)
InOrder(root.right)
def BacOrder(root):
'''后序遍历'''
if root == None:
return
BacOrder(root.left)
BacOrder(root.right)
print(root.val)
def BFS(root):
'''广度优先,层次遍历'''
if root == None:
return
# queue队列,保存节点
queue = []
# res保存节点值,作为结果
# vals = []
queue.append(root)
while queue:
# 拿出队首节点
currentNode = queue.pop(0)
# vals.append(currentNode.val)
print(currentNode.val)
if currentNode.left:
queue.append(currentNode.left)
if currentNode.right:
queue.append(currentNode.right)
def DFS(root):
'''深度优先遍历'''
if root == None:
return
# 栈用来保存未访问节点
stack = []
# vals保存节点值,作为结果
# vals = []
stack.append(root)
while stack:
# 拿出栈顶节点
currentNode = stack.pop()
# vals.append(currentNode.val)
print(currentNode.val)
if currentNode.right:
stack.append(currentNode.right)
if currentNode.left:
stack.append(currentNode.left)
if __name__=='__main__':
a = TreeNode(1)
b = TreeNode(2)
c = TreeNode(3)
d = TreeNode(4)
e = TreeNode(5)
f = TreeNode(6)
g = TreeNode(7)
h = TreeNode(8)
a.left = b
a.right = c
b.left = d
c.left = e
c.right = f
d.right = g
f.left = h
print('先序遍历:')
PreOrder(a)
print('中序遍历:')
InOrder(a)
print('后序遍历:')
BacOrder(a)
print('广度优先遍历:')
BFS(a)
print('深度优先遍历:')
DFS(a)
5. 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
栈其实就是列表,先进后出
队列,先进先出
题还是挺难的,有两个栈stackA、stackB,A是入栈的,B是出栈的,入栈时,直接进入A即可,出栈时,先判断是否有元素, 如果B没有元素,pop肯定报错,应该先将A中所有的元素压倒B里面,再pop最上面一个元素,如果B中有就直接pop出,就可以, 这是最优的思路,两个栈实现了先进后出,在一起又实现了队列的先进先出。
class Solution:
def __init__(self):
self.stackA = []
self.stackB = []
def push(self, node):
# write code here
self.stackA.append(node)
def pop(self):
# return xx
if self.stackB:
return self.stackB.pop()
elif not self.stackA:
return None
else:
while self.stackA:
self.stackB.append(self.stackA.pop())
return self.stackB.pop()
6.把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
这一题也不好解,在算法上,考虑数字没有重复的情况的话,使用二分法,有两个指针,第一个指针指向front,第二个指针指向rear, midIndex是中间数字,只要是旋转数组,那么首位一定大于中间位,所以如果首位大于中间位的话,那么就把指针从首位移到中间 位,前面数字向后移动,不断迭代,当首位和最后位只差1时,最后维就是最小值。此时最坏时间复杂度是O(logn),但是要考虑数字 重复的话,情况只可能是首位和末尾和中间重这种[1,0,1,1]只能取其中最小值,逐一排列,对于首位和中间位重的,比如[1,1,0], 把首位移动到后面去,可以处理,或者中间位和末尾重,比如[1,0,0],也是能处理,其他情况不存在,因为前提要求是旋转数组
class Solution:
def minNumberInRotateArray(self, rotateArray):
# write code here
if not rotateArray:
return 0
front, rear = 0, len(rotateArray) - 1
midIndex = 0
while rotateArray[front] >= rotateArray[rear]:
if rear - front == 1:
midIndex = rear
break
midIndex = (front + rear) // 2
if rotateArray[front] == rotateArray[midIndex] and rotateArray[front] == rotateArray[rear]:
return self.minOrder(rotateArray, front, rear)
if rotateArray[front] <= rotateArray[midIndex]:
front = midIndex
elif rotateArray[rear] >= rotateArray[midIndex]:
rear = midIndex
return rotateArray[midIndex]
def minOrder(self, array, front, end):
result = array[0]
for i in array[front:end + 1]:
if i < result:
result = i
return result
7.大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。n<=39
斐波那契数列:
0、1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)
#-*-coding:utf-8-*-
class Solution:
def Fibonacci(self, n):
# write code here
res = [0,1]
while len(res) <= n:
res.append(res[-1]+res[-2])
print(res)
return res[n]
so = Solution()
res = so.Fibonacci(3)
print(res)
8.一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
对于本题,前提只有 一次 1阶或者2阶的跳法。
a.如果两种跳法,1阶或者2阶,那么假定第一次跳的是一阶,那么剩下的是n-1个台阶,跳法是f(n-1);
b.假定第一次跳的是2阶,那么剩下的是n-2个台阶,跳法是f(n-2)
c.由a\b假设可以得出总跳法为: f(n) = f(n-1) + f(n-2)
d.然后通过实际的情况可以得出:只有一阶的时候 f(1) = 1 ,只有两阶的时候可以有 f(2) = 2
e.可以发现最终得出的是一个斐波那契数列:
| 1, (n=1)
f(n) = | 2, (n=2)
| f(n-1)+f(n-2) ,(n>2,n为整数)
#-*-coding:utf-8-*-
class Solution:
def jumpFloor(self, number):
#write code here
res = [1, 2]
while len(res) < number:
res.append(res[-1] + res[-2])
if number == 1:
return 1
elif number == 2:
return 2
else:
return res[number -1]
so = Solution()
res = so.jumpFloor(3)
print(res)
9.一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
因为n级台阶,第一步有n种跳法:跳1级、跳2级、到跳n级
跳1级,剩下n-1级,则剩下跳法是f(n-1)
跳2级,剩下n-2级,则剩下跳法是f(n-2)
所以f(n)=f(n-1)+f(n-2)+...+f(1)
因为f(n-1)=f(n-2)+f(n-3)+...+f(1)
所以f(n)=2*f(n-1)=
class Solution:
def jumpFloorII(self, number):
# write code here
return 2**(number-1)
10.我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
#-*-coding:utf-8-*-
class Solution:
def rectCover(self, number):
# write code here
if number == 0:
return 0
elif number == 1:
return 1
elif number == 2:
return 2
else:
res = [0, 1, 2]
while len(res) <= number:
res.append(res[-1] + res[-2])
return res[number]
11.输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
采用 python 自带了方法 bin 函数,比如 bin(12345) 回返回字符串 '0b11000000111001', 这个时候在把0b去掉即可。对于负数用补码表示。计算机中的负数是以其补码形式存在的 补码=原码取反+1。长度是32(整数一般是4个字节,一个字节8位,共有32位)其中一位最高位是符号位。表示模,如果n为负数的话,
+n就是补数,然后将补数变为补码就可以了。
可以去查看
https://blog.csdn.net/leonliu06/article/details/78685197
# -*- coding:utf-8 -*-
class Solution1:
def NumberOf1(self, n):
# write code here
return bin(n).replace("0b","").count("1") if n>=0 else bin(2**32+n).replace("0b","").count("1")
12. 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
直接这么写通过,0应该不算浮点数的,若只是负数,在python的计算中也没有问题
# -*- coding:utf-8 -*-
class Solution:
def Power(self, base, exponent):
# write code here
return base**exponent
13. 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
假设数组是1, 2, 4, 6, 9。如果是直接将9和2交换的话,会破坏偶数的相对位置,所以必须9先和6交换,然后9在和4交换,最后9和2交换一下就可以了。
下面的代码使用的是双指针
# -*- coding:utf-8 -*-
class Solution:
def reOrderArray(self, array):
k = 0 # /记录已经摆好位置的奇数的个数
i = 0 #遍历array的下标
n = len(array)
while i < n:
if array[i] % 2 == 1:
j = i
while j > k:
array[j], array[j - 1] = array[j - 1], array[j]
j -= 1
k += 1
i += 1
print(array)
return array
更加pythonic的话
# -*- coding:utf-8 -*-
class Solution:
def reOrderArray(self, array):
# write code here
k = 0 #/记录已经摆好位置的奇数的个数
for i,num in enumerate(array):
if num%2 == 1:
j = i
while(j > k):
array[j], array[j-1] = array[j-1], array[j]
j = j-1
k += 1
return array
class Solution:
def reOrderArray(self, array):
# write code here
array1 = []
array2 = []
for i in array:
array1.append(i) if int(i)%2==0 else array2.append(i)
# array2[len(array2):len(array1)]=
return array2 + array1
只是将后面的奇数换成前面的偶数,那是不行的,改变了偶数的相对位置,这时候也需要将偶数的位置也调整一下。
举个例子解释下面的代码:
假设array = [1,2,3,4,5,6,7]
当k=1,j=i=2,调整
当k=2,j=i=4,当前此时array=[1324567],首先调整45(此时array=[1325467]),然后调整35(此时array=[1352467)。
# -*- coding:utf-8 -*-
class Solution:
def reOrderArray(self, array):
# write code here
k = 0 #/记录已经摆好位置的奇数的个数
for i,num in enumerate(array):
if num%2 == 1:
j = i
while(j > k):
tem = array[j]
array[j]= array[j-1]
array[j-1] = tem
j = j-1
k += 1
return arra
14. 输入一个链表,输出该链表中倒数第k个结点
利用双指针,保持两者之间的距离是k-1 那么,当快指针走到末尾的时候,慢指针正好是倒数第k个节点
def FindKthToTail(self,head,k):
if not head:
return None
pFast = head
pSlow = head
for i in range(k-1):
if pFast.next:
pFast = pFast.next
else:
return None
while pFast.next:
pFast = pFast.next
pSlow = pSlow.next
return pSlow
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def FindKthToTail(self, head, k):
# write code here
res = []
while head:
res.append(head)
head = head.next
if k > len(res) or k<1:
return
return res[-k]
不是简单的使用上面的代码就可以运行了,因为ListNode只是一个一个节点,节点间的联系没有。这个需要参考
代码解释:里面使用了self.tail保证了self.head指向第一个节点,让self.tail.next指向下一个节点。
#-*-coding:utf-8-*
class Node():
'创建节点'
def __init__(self, data):
self.data = data
self.next = None
class Node():
'创建节点'
def __init__(self, data):
self.data = data
self.next = None
class LinkList():
'创建列表'
def __init__(self, node):
'初始化列表'
self.head = node
self.head.next = None
self.tail = self.head
def add_node(self, node):
'添加节点'
self.tail.next = node
self.tail = self.tail.next
def view(self):
'查看列表'
node = self.head
link_str = ''
while node is not None:
if node.next is not None:
link_str += str(node.data) + '-->'
else:
link_str += str(node.data)
node = node.next
print ('The Linklist is:' + link_str)
def FindKthToTail(self, k):
'查看具体节点'
index = self.length()-k+1
print('index:', index)
if index + 1 > self.length():
raise IndexError('index out of bounds')
num = 1
node = self.head
while True:
if num == index:
break
node = node.next
num += 1
return node.data
def length(self):
'列表长度'
node = self.head
count = 1
while node.next is not None:
count += 1
node = node.next
print ('The length of linklist are %d' % count)
return count
def delete_node(self, index):
'删除节点'
if index + 1 > self.length():
raise IndexError('index out of bounds')
num = 0
node = self.head
while True:
if num == index - 1:
break
node = node.next
num += 1
tmp_node = node.next
node.next = node.next.next
return tmp_node.data
def find_node(self, index):
'查看具体节点'
if index + 1 > self.length():
raise IndexError('index out of bounds')
num = 0
node = self.head
while True:
if num == index:
break
node = node.next
num += 1
return node.data
class Solution:
def FindKthToTail(self, head, k):
# write code here
res = []
while head:
res.append(head)
head = head.next
if k > len(res) or k<0:
return
return res[-k]
node1 = Node(1)
node2 = Node(2)
node3 = Node(3)
node4 = Node(4)
node5 = Node(5)
node6 = Node(6)
linklist = LinkList(node1)
linklist.add_node(node2)
linklist.add_node(node3)
linklist.add_node(node4)
linklist.add_node(node5)
linklist.add_node(node6)
linklist.view()
data = linklist.FindKthToTail(2)
print(data)
15.输入一个链表,反转链表后,输出新链表的表头。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回ListNode
def ReverseList(self, pHead):
# write code here
if not pHead or not pHead.next:
return pHead
pre = None
while pHead:
tmp = pHead.next
pHead.next = pre
pre = pHead
pHead = tmp
return pre
解析
这一题还是蛮难的。链表的翻转,例如 1->2->3->4->5 ==> 5->4->3->2->1
tmp = pHead.next 把当前节点的下一个节点保存下来
pHead.next = pre 把前一个节点移到当前节点的下一个节点,因为要翻转节点,pre始终指向要反转节点的首节点
pre = pHead 当前节点向后移一位
pHead = tmp 把之前保存的下一个节点指针再给当前节点接着翻转
16. 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
class Solution:
# 返回合并后列表
def Merge(self, pHead1, pHead2):
# write code here
if pHead1 == None:
return pHead2
elif pHead2 == None:
return pHead1
mergepHead = None
if pHead1.val <= pHead2.val:
mergepHead = pHead1
mergepHead.next = self.Merge(pHead1.next, pHead2)
elif pHead1.val > pHead2.val:
mergepHead = pHead2
mergepHead.next = self.Merge(pHead1, pHead2.next)
return mergepHead
# -*- coding:utf-8 -*-
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
# 返回合并后列表
def Merge(self, pHead1, pHead2):
# write code here
dummy = ListNode(0)
pHead = dummy
while pHead1 and pHead2:
if pHead1.val >= pHead2.val:
dummy.next = pHead2
pHead2 = pHead2.next
else:
dummy.next = pHead1
pHead1 = pHead1.next
dummy = dummy.next
if pHead1:
dummy.next = pHead1
elif pHead2:
dummy.next = pHead2
return pHead.next
17. 输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
先说下算法实现思路:对于两棵二叉树来说,要判断B是不是A的子结构,首先第一步在树A中查找与B根节点的值一样的节点。
通常对于查找树中某一个节点,我们都是采用递归的方法来遍历整棵树。
第二步就是判断树A中以R为根节点的子树是不是和树B具有相同的结构。
这里同样利用到了递归的方法,如果节点R的值和树的根节点不相同,则以R为根节点的子树和树B肯定不具有相同的节点;
如果它们值是相同的,则递归的判断各自的左右节点的值是不是相同。
递归的终止条件是我们达到了树A或者树B的叶节点。
class Solution:
def HasSubtree(self, pRoot1, pRoot2):
# write code here
result = False
# 判断根节点
if pRoot1 != None and pRoot2 != None:
if pRoot1.val == pRoot2.val:
result = self.same(pRoot1, pRoot2)
if not result:
result = self.HasSubtree(pRoot1.left, pRoot2)
if not result:
result = self.HasSubtree(pRoot1.right, pRoot2)
return result
def same(self, pRoot1, pRoot2):
if pRoot2 == None:
return True
if pRoot1 == None:
return False
# 这一步不断判断下一个节点,因为是递归操作。
if pRoot1.val != pRoot2.val:
return False
return self.same(pRoot1.left, pRoot2.left) and self.same(pRoot1.right, pRoot2.right)
18. 操作给定的二叉树,将其变换为源二叉树的镜像。
二叉树的镜像定义:源二叉树
8
/ \
6 10
/ \ / \
5 7 9 11
镜像二叉树
8
/ \
10 6
/ \ / \
11 9 7 5
class Solution:
# 返回镜像树的根节点
def Mirror(self, root):
# write code here
if root == None:
return root
root.left, root.right = root.right, root.left
self.Mirror(root.left)
self.Mirror(root.right)
19.输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
'''
思路超神:
可以模拟魔方逆时针旋转的方法,一直做取出第一行的操作
例如
1 2 3
4 5 6
7 8 9
输出并删除第一行后,
4 5 6
7 8 9
再进行一次逆时针旋转,就变成:
4 7 6 9
5 8 >>>>> 5 8
6 9 4 7
继续重复上述操作即可
# -*- coding:utf-8 -*-
class Solution:
# matrix类型为二维列表,需要返回列表
def printMatrix(self, matrix):
# write code here
result = []
while (matrix):
result += matrix.pop(0)
if not matrix:
break
matrix = self.turn(matrix)
return result
def turn(self, matrix):
newmat = []
row = len(matrix)
col = len(matrix[0])
for i in range(col):
newmat1 = []
for j in range(row):
newmat1.append(matrix[j][i])
newmat.append(newmat1)
newmat.reverse()
return newmat
注意result += matrix.pop(0),两个列表是可以相加的
a = [1,2,3]
b = [4,5,6]
c = a+b
c的结果:[1,2,3,4,5,6]
a = [1,2,3]
b = [4,5,6]
a.extend(b)
a的结果:[1,2,3,4,5,6]
>>> a = [1,2,3]
>>> a.reverse()
>>> a
[3, 2, 1]
20.定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。
我们可以设计两个栈:Stack和StackMin,一个就是普通的栈,另外一个存储push进来的最小值。
首先是push操作:
每次压入的数据newNum都push进Stack中,然后判断StackMin是否为空,如果为空那也把newNum同步压入StackMin里;
如果不为空,就先比较newNum和StackMin中栈顶元素的大小,如果newNum较大,那就不压入StackMin里,只压入一个最小值
否则就同步压入StackMin里。弹出时,同步弹出,这是一个栈结构。
class Solution:
def __init__(self):
self.stack = []
self.minstack = []
def push(self, node):
# write code here
self.stack.append(node)
if self.minstack == [] or node < self.min():
self.minstack.append(node)
else:
self.minstack.append(self.min())
def pop(self):
# write code here
if self.minstack == [] or self.stack == []:
return None
self.minstack.pop()
self.stack.pop()
def top(self):
# write code here
return self.stack[-1]
def min(self):
# write code here
return self.minstack[-1]
22.题目:从上往下打印出二叉树的每个节点,同层节点从左至右打印。
广度优先遍历
class Solution:
# 返回从上到下每个节点值列表,例:[1,2,3]
def PrintFromTopToBottom(self, root):
# write code here
if root == None:
return []
res = []
queue = []
queue.append(root)
while queue:
currentnode = queue.pop(0)
res.append(currentnode.val)
if currentnode.left:
queue.append(currentnode.left)
if currentnode.right:
queue.append(currentnode.right)
return res
23. 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
二叉搜索树即是二叉排序树,
1. 后序遍历序列的最后一个元素为二叉树的根节点;
2. 二叉搜索树左子树上所有的结点均小于根结点、右子树所有的结点均大于根结点。
算法步骤如下:
1. 找到根结点;
2. 遍历序列,找到第一个大于等于根结点的元素i,则i左侧为左子树、i右侧为右子树;
3. 我们已经知道i左侧所有元素均小于根结点,那么再依次遍历右侧,看是否所有元素均大于根结点;若出现小于根结点的元素,则直接返回false;若右侧全都大于根结点,则:
4. 分别递归判断左/右子序列是否为后序序列;
class Solution:
def VerifySquenceOfBST(self, sequence):
# write code here
if not sequence:
return False
root = sequence[-1]
i = 0
for node in sequence[:-1]:
if node > root:
break
i += 1
for node in sequence[i:-1]:
if node < root:
return False
left = True
# i>0 意味i =0 或者1 的时候,两个元素在二叉树没有排序之分的,但是3个元素就有了左右子树之分
if i > 0:
left = self.VerifySquenceOfBST(sequence[:i])
right = True
# len(sequence)>3才有左右之分的
if i < len(sequence) - 2 and left:
right = self.VerifySquenceOfBST(sequence[i + 1:])
return left and right
24.输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)
链接:https://www.nowcoder.com/questionTerminal/b736e784e3e34731af99065031301bca?f=discussion
递归问题。首先考虑特殊情况,即输入二叉树为空或者不存在子结点的情况。再考虑一般情况,如果存在子结点,判断以子结点为根结点的二叉树是否能找到和为【原期望值-原根节点值】的路径,如果存在,返回路径列表,不存在则返回空列表。因为二叉树可能有左右两个子结点,所以需要将左右子树的返回列表合并,若列表不为空,证明存在满足条件的路径,再在每条路径下加入根节点的值即可,否则返回空列表。
class Solution:
# 返回二维列表,内部每个列表表示找到的路径
def FindPath(self, root, expectNumber):
# write code here
if not root:
return []
if root.left is None and root.right is None:
if root.val==expectNumber:
return [[root.val]]
else:
return []
else:
pathl=[]
pathr=[]
if root.left is not None:
pathl=self.FindPath(root.left,expectNumber-root.val)
if root.right is not None:
pathr=self.FindPath(root.right,expectNumber-root.val)
path=pathl+pathr
if path:
for each in path:
each.insert(0,root.val)
return path
25.输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
26.输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
思路:由于输入的一个二叉搜索树,其左子树大于右子树的值,这位后面的排序做了准备,因为只需要中序遍历即可,将所有
的节点保存到一个列表,。对这个list[:-1]进行遍历,每个节点的right设为下一个节点,下一个节点的left设为上一个节点。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def Convert(self, pRootOfTree):
# write code here
if not pRootOfTree:
return
self.attr = []
self.midorder(pRootOfTree)
for i, v in enumerate(self.attr[:-1]):
v.right = self.attr[i + 1]
self.attr[i + 1].left = v
return self.attr[0]
def midorder(self, root):
if not root:
return
self.midorder(root.left)
self.attr.append(root)
self.midorder(root.right)
27.输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
#-*-coding:utf-8-*-
class Solution:
def printAllSub(self, s, i, res):
if i == len(s):
print(res)
return
self.printAllSub(s, i+1, res)
self.printAllSub(s, i+1, res+s[i])
so = Solution()
s = 'abc'
so.printAllSub(s, 0, '')
# -*- coding:utf-8 -*-
class Solution:
def Permutation(self, ss):
# write code here
if len(ss) == 0:
return []
if len(ss) == 1:
return [ss]
res = set()
#遍历字符串,固定第一个元素,第一个元素可以取a,b,c...全部取到,然后递归求解
for i in range(len(ss)):
for j in self.Permutation(ss[:i] + ss[i+1:]):#依次固定了元素,然后递归求解
res.add(ss[i]+j) #set集合添加元素的方法add(),集合添加去重(若存在重复字符,排列后会存在相同情况)
return sorted(res)
28.数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
# -*- coding:utf-8 -*-
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
# write code here
dict = {}
for number in numbers:
if number not in dict:
dict[number] = 1
else:
dict[number] += 1
if dict[number] > len(numbers)/2:
return number
return 0
29.输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
选择排序算法:
# -*- coding:utf-8 -*-
class Solution:
def GetLeastNumbers_Solution(self, tinput, k):
if len(tinput) < k:
return []
for i in range(k):
midindex = i
for j in range(i, len(tinput)):
if tinput[j] < tinput[midindex]:
tinput[j], tinput[midindex] = tinput[midindex], tinput[j]
return tinput[:k]
30.HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)
动态规划初级题目,做完之后,可以试试最大子矩阵和(https://www.nowcoder.com/questionTerminal/a5a0b05f0505406ca837a3a76a5419b3)
该题目思路:
dp[i]表示以元素array[i]结尾的最大连续子数组和.
以[-2,-3,4,-1,-2,1,5,-3]为例
可以发现,
dp[0] = -2
dp[1] = -3
dp[2] = 4
dp[3] = 3
以此类推,会发现
dp[i] = max{dp[i-1]+array[i],array[i]}.
# -*- coding:utf-8 -*-
class Solution:
def FindGreatestSumOfSubArray(self, array):
m = len(array)
dp = [i for i in array]
for i in range(1, m):
dp[i] = max(dp[i-1]+array[i], array[i])
return max(dp)
31.求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
思路1:例:对于824883294,先求0-800000000之间(不包括800000000)的,再求0-24883294之间的。
如果等于1,如1244444,先求0-1000000之间,再求1000000-1244444,那么只需要加上244444+1,再求0-244444
之间的1如果大于1,例:0-800000000之间1的个数为8个100000000的1的个数加上100000000,因为从1000000000-
200000000共有1000000000个数且最高位都为1。对于最后一位数,如果大于1,直接加上1即可。
思路2:将1-n全部转换为字符串,只需要统计每个字符串中'1'出现的次数并相加即可
class Solution:
def NumberOf1Between1AndN_Solution(self, n):
# write code her
result = 0
if n < 0:
return 0
length = len(str(n))
listN = list(str(n))
for i, v in enumerate(listN):
a = length - i - 1 # a为10的幂
if i==length-1 and int(v)>=1:
result+=1
break
if int(v) > 1:
result += int(10 ** a * a / 10) * int(v) + 10**a
if int(v) == 1:
result += (int(10 ** a * a / 10) + int("".join(listN[i+1:])) + 1)
return result
# -*- coding:utf-8 -*-
class Solution:
def NumberOf1Between1AndN_Solution(self, n):
# 将1-n全部转换为字符串
# 只需要统计每个字符串中'1'出现的次数并相加即可
count = 0
for i in range(1,n+1):
for i in str(i):
if i == '1':
count += 1
return count
32.输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
使用选择排序做的
# -*- coding:utf-8 -*-
class Solution:
def PrintMinNumber(self, numbers):
# write code here
if not numbers:
return ''
numbers = list(map(str, numbers))
n = len(numbers)
for i in range(n-1):
max_index = i
for j in range(i, n):
if numbers[j] + numbers[max_index] < numbers[max_index]+numbers[j]:
max_index = j
if not max_index == i:
numbers[max_index], numbers[i] = numbers[i], numbers[max_index]
return ''.join(numbers).lstrip('0') or'0'
python2的代码
class Solution:
def PrintMinNumber(self, numbers):
# write code here
if not numbers: return ""
numbers = list(map(str, numbers))
numbers.sort(cmp=lambda x, y: cmp(x + y, y + x))
return "".join(numbers).lstrip('0') or'0
如果希望元素能按照特定的方式进行排序,给cmp赋值
cmp(x,y) 函数用于比较2个对象,如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1。在python2中有
Python join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串。
>>> str='_'
>>> seq = ['a', 'b', 'c']
>>> str.join(seq)
'a_b_c'
Python lstrip() 方法用于截掉字符串左边的空格或指定字符。
python3的代码
import operator
# -*- coding:utf-8 -*-
class Solution:
def PrintMinNumber(self, numbers):
# write code here
if not numbers:
return ''
numbers = list(map(str, numbers))
# 在python3.x中已经没有cmp函数,要是用operator函数进行比较,cmp函数就是比较输入两个字符串之间大小的数字
# cmp(x,y) 函数用于比较2个对象,如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1。
# 是两两对象之间的比较,排序默认是从小到大,在这个函数内部实现的两两排序
numbers.sort(cmp=lambda x, y: operator.eq(x + y, y + x))
if numbers[0] == '0':
return 0
else:
# ''.join实现了字符串之间的连接
return ''.join(numbers)
33.把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
思路:按顺序把每个丑数放在数组中,求下一个丑数
下一个丑数必定由有数组中的某一个丑数A * 2, B * 3, C * 5 的中的最小值得来。
分析:在数组中必定有一个丑数M2, 在它之前的数 * 2 都小于当前最大丑数, 在它之后的数 * 2都大于当前最大丑数,
同样有M3, M5
# -*- coding:utf-8 -*-
class Solution:
def GetUglyNumber_Solution(self, index):
# write code here
if index < 1:
return 0
res = [1]
t2 = t3 = t5 = 0
nextdex = 1
while nextdex < index:
minNum = min(res[t2] * 2, res[t3] * 3, res[t5] * 5)
res.append(minNum)
if res[t2] * 2 <= minNum:
t2 += 1
if res[t3] * 3 <= minNum:
t3 += 1
if res[t5] * 5 <= minNum:
t5 += 1
nextdex += 1
return res[nextdex - 1]
34.在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
# -*- coding:utf-8 -*-
class Solution:
def InversePairs(self, data):
# write code here
copy = []
count = 0
for i in data:
copy.append(i)
copy.sort()
for i in range(len(copy)):
count += data.index(copy[i])
data.remove(copy[i])
return count % 10000000007
# -*- coding:utf-8 -*-
class Solution:
def InversePairs(self, data):
# write code here
self.arr, self.count = data, 0
self.merge_sort(0, len(data)-1)
return self.count % 1000000007
def merge_sort(self, l, r):
if l >= r: return
m = int((l+r+1)/2)
self.merge_sort(l, m-1)
self.merge_sort(m, r)
i, j, merge = l, m, []
while i < m and j <= r:
if self.arr[i] < self.arr[j]:
merge.append(self.arr[i])
i += 1
else:
merge.append(self.arr[j])
j += 1
self.count += m - i
for x in range(j,r+1): merge.append(self.arr[x])
for x in range(i,m): merge.append(self.arr[x])
for i in range(l, r+1): self.arr[i] = merge[i-l]
35. 输入两个链表,找出它们的第一个公共结点。
思路:共同节点,意味着从共同节点开始之后所有的节点数都是相同的,这是链表,只要有一个共同节点,那么之后所有的指向
也是重复的。先依次遍历两个链表,记录两个链表的长度m和n,如果 m > n,那么我们就先让长度为m的链表走m-n个结点,然后
两个链表同时遍历,当遍历到相同的结点的时候停止即可。对于 m < n,同理。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
# write code here
Length1 = self.GetLength(pHead1)
Length2 = self.GetLength(pHead2)
LengthDiff = abs(Length1 - Length2)
if Length1 > Length2:
pHeadLong = pHead1
pHeadShort = pHead2
else:
pHeadLong = pHead2
pHeadShort = pHead1
for i in range(LengthDiff):
pHeadLong = pHeadLong.next
while pHeadLong != None and pHeadShort != None and pHeadLong != pHeadShort:
pHeadLong = pHeadLong.next
pHeadShort = pHeadShort.next
return pHeadLong
def GetLength(self, pHead):
length = 0
while pHead:
pHead = pHead.next
length += 1
return length
37.统计一个数字在排序数组中出现的次数。
class Solution:
def GetNumberOfK(self, data, k):
# write code here
return data.count(k)
38. 输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
思路:利用递归实现。如果一棵树只有一个结点,那么它的深度为1。递归的时候无需判断左右子树是否存在,因为如果该节点
为叶节点,它的左右子树不存在,那么在下一级递归的时候,直接return 0。同时,记得每次递归返回值的时候,深度加一操
作,因为计算深度是从根节点下面一个节点开始计算的。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def TreeDepth(self, pRoot):
# write code here
if pRoot == None:
return 0
return max(self.TreeDepth(pRoot.left), self.TreeDepth(pRoot.right)) + 1
39. 输入一棵二叉树,判断该二叉树是否是平衡二叉树
如果二叉树的每个节点的左子树和右子树的深度不大于1,它就是平衡二叉树。
class Solution:
def IsBalanced_Solution(self, pRoot):
# write code here
if pRoot == None:
return True
if abs(self.Depth(pRoot.left) - self.Depth(pRoot.right)) > 1:
return False
return self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right)
def Depth(self, root):
if root == None:
return 0
return max(self.Depth(root.left), self.Depth(root.right)) + 1
40. 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
class Solution:
# 返回[a,b] 其中ab是出现一次的两个数字
def FindNumsAppearOnce(self, array):
# write code here
dt = {}
res = []
for i in array:
if i not in dt:
dt[i] = 1
else:
dt[i] += 1
for i in dt:
if dt[i] == 1:
res.append(i)
return res
41. 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
引申:
如何求递增数组中两个数字和为目标的问题
[1, 2, 3, 4] 求出和为 5的两个数。 结果为[1, 4], [2, 3]
思路:
- 维持最小变量small, 最大变量 big. 如果small + big == target, small向前移动一位,big向后移动一位
- 如果small + big > target, 则要缩小和, big向前移动。否则, small向前移动增大和
回到本问题
- 同样有small, big. 初始值为1, 2。target为N
- 序列和(small到big) > target,同样要缩小和, small向前移动一位,则序列和减小small。否则增大和,big向前移动一位,序列和增大big
- 如果相同,则保存下来。然后small向前移动两位, big向前移动一位(自己想想为什么,假设相等时候为a,a+1,a+2,往前移动1个必有a+1+a+2+a+3 > a+a+1+a+2)
- 如此循环直到 small >= (1 + target) /2, 因为此时big + small 肯定大于target(题目要求最少两位)
# -*- coding:utf-8 -*-
class Solution:
def FindContinuousSequence(self, tsum):
# write code here
if tsum < 3:
return []
small = 1
big = 2
middle = (tsum+1)/2
res = []
cursum = small + big
while small < middle:
if cursum == tsum:
res.append((range(small, big+1)))
small += 2
big += 1
cursum -= small * 2 - 3
cursum += big
elif cursum < tsum:
big += 1
cursum += big
else:
cursum -= small
small += 1
return res
42.输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
输出描述:
对应每个测试案例,输出两个数,小的先输出。
# -*- coding:utf-8 -*-
class Solution:
def FindNumbersWithSum(self, array, tsum):
# write code here
left, right = 0, len(array)-1
while left < right:
if array[left] + array[right] == tsum:
return [array[left], array[right]]
elif array[left] + array[right] > tsum:
right -= 1
else:
left += 1
return []
43. 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!
class Solution:
def LeftRotateString(self, s, n):
# write code here
return s[n:] + s[:n]
44. 牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?
# -*- coding:utf-8 -*-
class Solution:
def ReverseSentence(self, s):
# write code here
return ' '.join(s.split(' ')[::-1])
47. 求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
# -*- coding:utf-8 -*-
class Solution:
def Sum_Solution(self, n):
# write code here
return sum(list(range(1, n+1)))
48. 写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
思路二:
首先看十进制是如何做的: 5+7=12,三步走
第一步:相加各位的值,不算进位,得到2。
第二步:计算进位值,得到10. 如果这一步的进位值为0,那么第一步得到的值就是最终结果。
第三步:重复上述两步,只是相加的值变成上述两步的得到的结果2和10,得到12。
同样我们可以用三步走的方式计算二进制值相加: 5-101,7-111 第一步:相加各位的值,不算进位,得到010,
二进制每位相加就相当于各位做异或操作,101^111。
第二步:计算进位值,得到1010,相当于各位做与操作得到101,再向左移一位得到1010,(101&111)<<1。
第三步重复上述两步, 各位相加 010^1010=1000,进位值为100=(010&1010)<<1。
继续重复上述两步:1000^100 = 1100,进位值为0,跳出循环,1100为最终结果。\
class Solution:
def Add(self, num1, num2):
# write code here
while num2:
# 异或运算相当于只求和不进位
sum = num1 ^ num2
# 与操作,并向左移一位,相当于求进位
carray = (num1 & num2) << 1
num1 = sum
num2 = carray
return num1
48.在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
# -*- coding:utf-8 -*-
class Solution:
# 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
# 函数返回True/False
def duplicate(self, numbers, duplication):
# write code here
if not numbers:
return False
for i in range(len(numbers)):
if numbers.count(numbers[i])>1:
duplication[0]=numbers[i]
return True
return False
49.把字符串转换为整数
将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。
输入
+2147483647
1a33输出
2147483647
0
# -*- coding:utf-8 -*-
class Solution:
def StrToInt(self, s):
numlist = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
sum = 0
label = 1 # 正负数标记
if s == '':
return 0
if s[0] == '+':
s = s[1:]
label = 1
elif s[0] == '-':
s = s[1:]
label = -1
for c in s:
if c in numlist:
sum = sum*10 + numlist.index(c)
else:
return 0
return sum*label
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]。不能使用除法。
# -*- coding:utf-8 -*-
class Solution:
def multiply(self, A):
B = []
for i in range(len(A)):
sum = 1
for j in range(len(A)):
if i == j:
continue
sum = sum * A[j]
B.append(sum)
return B
# -*- coding:utf-8 -*-
class Solution:
def multiply(self, A):
n = len(A)
B = [0 for _ in range(n)]
B[0] = 1
temp = 1
for i in range(1, n):
B[i] = B[i-1]*A[i-1]
print(B)
for j in range(n-2, -1, -1):
temp *= A[j+1]
B[j] *= temp
return B
53. 请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。
54.字符流中第一个不重复的字符
题目:请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
class Solution:
def __init__(self):
self.s=""
def FirstAppearingOnce(self):
res=list(filter(lambda c:self.s.count(c)==1,self.s))
return res[0] if res else "#"
def Insert(self, char):
self.s+=char
55.链表中环的入口节点
题目:一个链表中包含环,请找出该链表的环的入口结点。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def EntryNodeOfLoop(self, pHead):
# write code here
slow,fast=pHead,pHead
while fast and fast.next:
slow=slow.next
fast=fast.next.next
if slow==fast:
slow2=pHead
while slow!=slow2:
slow=slow.next
slow2=slow2.next
return slow
class Solution:
def EntryNodeOfLoop(self, pHead):
# write code here
linkls = []
while pHead:
if pHead in linkls:
return pHead
linkls.append(pHead)
pHead = pHead.next
return None
56.删除链表中重复的节点
题目:在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5。
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def deleteDuplication(self, pHead):
# write code here
if pHead == None or pHead.next == None:
return pHead
new_head = ListNode(-1)
new_head.next = pHead
pre = new_head
pre.next = pHead
nex = None
while pHead != None and pHead.next != None:
nex = pHead.next
if pHead.val == nex.val:
while nex != None and nex.val == pHead.val:
nex = nex.next
pre.next = nex
pHead = nex
else:
pre = pHead
pHead = pHead.next
return new_head.next
class Solution:
def deleteDuplication(self, pHead):
res = []
while pHead:
res.append(pHead.val)
pHead = pHead.next
res = list(filter(lambda c: res.count(c) == 1, res))
dummy = ListNode(0)
pre = dummy
for i in res:
node = ListNode(i)
pre.next = node
pre = pre.next
return dummy.next
57.二叉树的下一个节点
题目:给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
思路,如果这道题是求中序遍历,肯定很简单。所以我们先写一个中序遍历的算法。关键是从根节点开始遍历,所以第一步还是找到某个节点的根节点,方法是一直使用next判断即可。
再将从根节点中序遍历的结果保存到一个数组中,直接找pNode所在索引的下一个即可。当然要考虑这个节点是不是最后一个,如果是最后一个,直接返回None。
# -*- 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
dummy = pNode
while dummy.next:
dummy = dummy.next
self.result = []
self.midTraversal(dummy)
return self.result[self.result.index(pNode) + 1] if self.result.index(pNode) != len(self.result) - 1 else None
def midTraversal(self, root):
if not root: return
self.midTraversal(root.left)
self.result.append(root)
self.midTraversal(root.right)
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):
if not pRoot:
return True
return self.compare(pRoot.left, pRoot.right)
def compare(self, pRoot1, pRoot2):
if not pRoot1 and not pRoot2:
return True
if not pRoot1 or not pRoot2:
return False
if pRoot1.val == pRoot2.val:
if self.compare(pRoot1.left, pRoot2.right) and self.compare(pRoot1.right, pRoot2.left):
return True
return False
60.从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
# -*- 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):
if not pRoot:
return []
result = []
stackA = [pRoot]
while stackA:
stackB = []
res = []
for node in stackA:
res.append(node.val)
if node.left:
stackB.append(node.left)
if node.right:
stackB.append(node.right)
stackA = stackB
result.append(res)
return result
61.序列化二叉树
请实现两个函数,分别用来序列化和反序列化二叉树
二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。
二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def __init__(self):
self.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。
二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
二叉排序树的中序遍历就是排序
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回对应节点TreeNode
def KthNode(self, pRoot, k):
self.res=[]
self.dfs(pRoot)
return self.res[k-1] if 0<k<=len(self.res) else None
def dfs(self,root):
if not root:return
self.dfs(root.left)
self.res.append(root)
self.dfs(root.right)
63.数据流中的中位数
题目:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.s = []
def Insert(self, num):
# write code here
self.s.append(num)
def GetMedian(self,f):
# write code here
self.s.sort()
if len(self.s) % 2 == 1:
return self.s[len(self.s)//2]
else:
return (self.s[len(self.s)//2] + self.s[len(self.s)//2-1])/2.0
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]}。
class Solution:
def maxInWindows(self, num, size):
n = len(num)
if size == 0:
return []
if n < size:
return []
size_max = []
for i in range(n - size + 1):
size_max.append(max(num[i:i + size]))
return size_max
65.矩阵中的路径
题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 a b c e s f c s a d e e 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
# -*-coding:utf-8-*-
class Solution:
def hasPath(self, matrix, rows, cols, path):
# write code here
if not matrix:
return False
if not path:
return True
x = [list(matrix[cols * i:cols * i + cols]) for i in range(rows)]
print(x)
for i in range(rows):
for j in range(cols):
if self.exist_helper(x, i, j, path):
return True
return False
def exist_helper(self, matrix, i, j, p):
if matrix[i][j] == p[0]:
if not p[1:]:
return True
matrix[i][j] = ''
if i > 0 and self.exist_helper(matrix, i - 1, j, p[1:]):
return True
if i < len(matrix) - 1 and self.exist_helper(matrix, i + 1, j, p[1:]):
return True
if j > 0 and self.exist_helper(matrix, i, j - 1, p[1:]):
return True
if j < len(matrix[0]) - 1 and self.exist_helper(matrix, i, j + 1, p[1:]):
return True
matrix[i][j] = p[0]
66.机器人的运动范围
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
#-*-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
tmpi = list(map(int, list(str(i))))
tmpj = list(map(int, list(str(j))))
if sum(tmpi) + sum(tmpj) > 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)
67. 剪绳子
给你一根长度为n的绳子,请把绳子剪成m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m]。请问k[0]xk[1]x...xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
# -*- coding:utf-8 -*-
class Solution:
def cutRope(self, number):
if number < 2:
return 0
if number == 2:
return 1
if number == 3:
return 2
if number == 4:
return 4
num_3 = number / 3
if number - num_3*3 == 2:
return 3**num_3*2
return 3**num_3