python版剑指offer(第二版)面试题及答案

面试题1:略

面试题2:略

面试题3:数组中重复的数字

题目一:找出数组中重复的数字

在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出重复的数字是2或3。

#测试数据
a = [2,3,1,0,2,5,3]

#改变数组
def findRepeatNum(arr):
	if arr==None or len(arr) < 2:
		return -1
	for a in arr:
		if a < 0 or a >= len(arr):
			return -1
	i = 0
	while i < len(arr):
		if arr[i] == i:
			i += 1
		else:
			if arr[arr[i]] == arr[i]:
				for a in arr:
					print(a, end=' ')
				print()
				return arr[i]
			else:
				tmp = arr[arr[i]]
				arr[arr[i]] = arr[i]
				arr[i] = tmp
	return -1
题目二:不修改数组找出重复的数字

在一个长度为n+1的数组里的所有数字都在1~n范围内,所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但不能修改输入的数组。例如,如果输入长度为8的数组{2,3,5,4,3,2,6,7},那么对应的输出是重复的数字2或者3。

#不改变数组
b=[2,3,5,4,3,2,6,7]
c=[2,1,5,4,2,3]
def findRepeatNum2(arr):
	if arr==None or len(arr) < 2:
		return -1
	for a in arr:
		if a < 1 or a >= len(arr):
			return -1
	def rangeCount(arr, lens, start, end):
		num = 0
		for i in range(lens):
			if arr[i] >= start and arr[i] <= end:
				num += 1
		return num		
	start = 1
	end = len(arr) - 1
	while start <= end:
		mid = start + ((end - start) >> 1)
		count = rangeCount(arr, len(arr), start, mid)
		if start == end:
			if count > 1:
				return start
			else:
				break
		if count > mid - start + 1 :
			end = mid
		else:
			start = mid + 1
	return -1

面试题4:二维数组中的查找

题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

#测试数据
m=[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]

def findTwoDimensionalArray(twoDiArray, k):
	if twoDiArray == None:
		return False
	import numpy as np
	rows = np.shape(twoDiArray)[0]
	cols = np.shape(twoDiArray)[1]
	if rows == 0 or cols == 0:
		return False
	if twoDiArray[rows - 1][cols - 1] < k or twoDiArray[0][0] > k:
		return False
	row = 0
	col = cols - 1
	while row < rows and col >= 0:
		if twoDiArray[row][col] < k:
			row += 1
		else:
			if twoDiArray[row][col] == k:
				return True
			elif twoDiArray[row][col] > k:
				col -= 1
			else:
				return False
	return False

面试题5:替换空格

题目:请实现一个函数,把字符串中的每个空格替换成"%20",例如,输入"We are happy.“,则输出"We%20are%20happy.”

def replaceBlankSpace(strs):
	num = 0
	lens = len(strs)
	for s in strs:
		if s == ' ':
			num += 1
	strs =  strs + ' ' * num * 2
	strs = list(strs)
	i = len(strs) - 1
	j = lens - 1
	while i >= 0 and j >= 0:
		if strs[j] != ' ':
			strs[i] = strs[j]
			i -= 1
			j -= 1
		else:
			strs[i] = '0'
			strs[i - 1] = '2'
			strs[i - 2] = '%'
			i -= 3
			j -= 1
	print(''.join(strs))
	return ''.join(strs)

replaceBlankSpace("hello world")

面试题6:从尾到头打印链表

题目:输入一个链表的头节点,从尾到头反过来打印每个节点的值。链表节点定义如下:
struct ListNode
{
int m_nKey;
ListNode* m_pNext;
};

#定义链表节点
class ListNode():
	def __init__(self, value, next=None):
		self.value = value
		self.next = next
#方法一:(通过栈存储值,再依次弹出的方法,此处省略)
#方法二:递归法
def inversePrint(head):
	if head != None:
		if head.next != None:
			inversePrint(head.next)
		print(head.value)
	return
#递归法之另一种写法
def inversePrint(head):
    if head == None:
        return
    inversePrint(head.next)
    print(head.value)
#测试数据
head = ListNode(3)
mid = ListNode(2)
tail = ListNode(1)
head.next = mid
mid.next = tail
inversePrint(head)

面试题7:重建二叉树

题目:输入某二叉树的前序和中序遍历的结果,请重建该二叉树。假设输入的前序和中序遍历的结果中都不含重复数字。例如,输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建如下图(7-1)所示的二叉树并输出它的头节点。二叉树节点的定义如下:
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};

图7-1
    1
   / \
  2   3
 /   / \
4   5   6
 \     /
  7   8
#定义二叉树节点
class BinaryTreeNode():
	def __init__(self, value, left = None, right = None):
		self.value = value
		self.left = left
		self.right = right

def rebulidTree(preOrder, midOrder):
	lens = len(preOrder)
	if lens <= 0:
		return None
	value = preOrder[0]
	binaryTree = BinaryTreeNode(value)
	idxV = midOrder.index(value)
	leftM = midOrder[ : idxV]
	rightP = midOrder[idxV + 1 : ]
	leftP = preOrder[1 : idxV + 1]
	rightM = preOrder[idxV + 1 : ]
	lTree = rebulidTree(leftP, leftM)
	rTree = rebulidTree(rightP, rightM)
	binaryTree.left = lTree
	binaryTree.right = rTree
	return binaryTree
 
 #测试数据
binaryTree = rebulidTree([1,2,4,7,3,5,6,8], [4,7,2,1,5,3,8,6])
print(binaryTree.value)
print(binaryTree.left.left.right.value)

面试题8:二叉树的下一个节点

题目:给定一棵二叉树和其中的一个节点,如何找出中序遍历的下一个节点?树中的节点除了有两个分别指向左、右子节点的指针,还有一个指向父节点的指针。
图8-1中二叉树的中序遍历序列是{d,b,h,e,i,a,f,c,g}

图8-1
       a
     /   \    
   b       c   
  / \     / \  
 d   e   f   g
    / \
   h   i
#二叉树节点的定义,包含指向父节点的指针
class BinaryTreeNode2():
	def __init__(self, value, left = None, right = None, parent = None):
		self.value = value
		self.left = left
		self.right = right
		self.parent = parent
#根据题意,给定一个节点,意味着,已经存在一棵树,不用再显性给出一棵树头节点
def findNextTreeNode(treeNode):
	nextNode = None
	if treeNode == None:
		return nextNode 
	#如果treeNode存在右子节点(即右子节点不为空)(此情况包含treeNode为根节点的情况)
	nextNode = treeNode.right 
	if nextNode != None:
		while nextNode.left != None:
			nextNode = nextNode.left
		return nextNode
	#如果为左子节点且该节点的右子节点为空
	if treeNode.parent != None and treeNode.parent.left == treeNode:
		return treeNode.parent
	#如果为右子节点且该节点的右子节点为空
	if treeNode.parent != None and treeNode.parent.right == treeNode:
		parentNode = treeNode.parent
		while parentNode != None and parentNode.right == treeNode:
			treeNode = parentNode
			parentNode = parentNode.parent
		return parentNode
	return nextNode
	
#方法二:递归
def getNextNode(node):
    if node == None:
        return node
    
    def getNodeFuzhu(node):
        if node.left == None:
            return node
        else:
            return getNodeFuzhu(node.left)
        
    if node.right != None:
        rightN = node.right
        return getNodeFuzhu(rightN) 
    elif node.parent != None and node.parent.right != node:
        return node.parent
    else:
        return None	
#测试数据
a = BinaryTreeNode2('a')
b = BinaryTreeNode2('b')
c = BinaryTreeNode2('c')
d = BinaryTreeNode2('d')
e = BinaryTreeNode2('e')
f = BinaryTreeNode2('f')
g = BinaryTreeNode2('g')
h = BinaryTreeNode2('h')
i = BinaryTreeNode2('i')
a.left = b
a.right = c
b.parent = a
b.left = d
b.right = e
c.parent = a
c.left = f
c.right = g
d.parent = b
e.parent = b
e.left = h
e.right = i
f.parent = c
g.parent = c
h.parent = e
i.parent = e
print(findNextTreeNode(i).value)

面试题9:用两个栈实现队列(答案:略)

题目:用两个栈实现一个队列。队列的声明如下,请实现他的两个函数appendTail和deleteHead,分别完成在队列尾部插入节点和在队列头部删除节点的功能。

面试题10:斐波那契数列

题目一:求斐波那契数列的第n项

写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项。斐波那契数列的定义如下:
在这里插入图片描述

def fbnq(n):
	if n <= 0:
		return 0
	if n == 1:
		return 1
	last_second = 0
	last_first = 1
	res = 0
	for x in range(2, n + 1):
		res = last_first + last_second
		last_second = last_first
		last_first = res
	return res

#测试数据
print(fbnq(9) + fbnq(10))
print(fbnq(11))
题目二:青蛙跳台阶问题

一个青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个n级的台阶总共有多少种跳法。

def frogJump(n):
	if n <= 0:
		return 0
	if n == 1:
		return 1
	if n == 2:
		return 2
	first = 1
	second = 2
	res = 0
	for i in range(3, n + 1):
		res = first + second
		first = second 
		second = res
	return res

面试题11:旋转数组的最小数字

题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。

def minRotateArray(arr):
	if arr == None:
		return
	first = 0
	last = len(arr) - 1
	mid = (last + first) >> 1
	def getMin(arr, first, last):
		res = arr[first]
		for i in range(first , last + 1):
			if res > arr[i]:
				res = arr[i]
		return res
	while arr[first] >= arr[last]:
		if last - first == 1:
			return arr[last]
		mid = (last + first) >> 1
		if arr[first] == arr[mid] and arr[mid] == arr[last]:
			return getMin(arr, first, last)
		elif arr[first] <= arr[mid]:
			first = mid
		elif arr[mid] <= arr[last]:
			last = mid
	return arr[mid] 

面试题12:矩阵中的路径

题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3×4的矩阵中包含一条字符串"bfce"的路径(路径中的字母用下划线标出)。但矩阵中不包含字符串"abfb"的路径,因为字符串中的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。

abtg
cfcs
jdeh
def pathInMatrix(matrix, rows, cols, strs):
    matrixBool = [[False] * cols for i in range(rows)]
    lens = len(strs)
    idx = 0
    def hasPathCore(matrix, matrixBool, rows, cols, row, col, strs, lens, idx):
        if idx == lens:
            return True
        if row < 0 or row >= rows or col < 0 or col >= cols:
            return False
        res = False
        if matrix[row][col] == strs[idx] and matrixBool[row][col] == False:
            matrixBool[row][col] = True
            res = hasPathCore(matrix, matrixBool, rows, cols, row + 1, col, strs, lens, idx + 1) or \
                  hasPathCore(matrix, matrixBool, rows, cols, row - 1, col, strs, lens, idx + 1) or \
                  hasPathCore(matrix, matrixBool, rows, cols, row, col + 1, strs, lens, idx + 1) or \
                  hasPathCore(matrix, matrixBool, rows, cols, row, col - 1, strs, lens, idx + 1)
            if res == False:
                matrixBool[row][col] = False
        return res
    for row in range(rows):
        for col in range(cols):
            if hasPathCore(matrix, matrixBool, rows, cols, row, col, strs, lens, idx):
                return True 
    return False

#测试数据
matrix = [['a','b','t','g'],['c','f','c','s'],['j','d','e','h']]
print(pathInMatrix(matrix, 3, 4, 'acjdfb'))

面试题13:机器人的运动范围

题目:地上有一个m行n列的方格。一个机器人从坐标(0, 0)的格子开始移动,它每次可以向左、右、上、下移动一格,但不能进入行坐标和列坐标的位数之和k的格子。例如,当k为18时,机器人能够进入方格(35, 37),因为3+5+3+7=18。但它不能进入方格(35, 38),因为3+6+3+8=19。请问该机器人能够到达多少个格子?

def robotRangeBacktrace(rows, cols, threshold):
	if rows <= 0 or cols <= 0 or threshold < 0:
		return 0
	booleans = [[False] * cols for i in range(rows)] 
	def numSum13(x):
		res = 0
		while x > 0:
			res += (x - x // 10 * 10)
			x = x // 10 
		return res
	def robotRangeBacktraceCore(row, col, rows, cols, threshold, booleans):
		count = 0
		if row >= 0 and col >= 0 and row < rows and col < cols \
			and booleans[row][col] == False and numSum13(row) + numSum13(col) <= threshold:
			booleans[row][col] = True
			count = 1 + robotRangeBacktraceCore(row + 1, col, rows, cols, threshold, booleans)\
					  + robotRangeBacktraceCore(row - 1, col, rows, cols, threshold, booleans)\
					  + robotRangeBacktraceCore(row, col + 1, rows, cols, threshold, booleans)\
					  + robotRangeBacktraceCore(row, col - 1, rows, cols, threshold, booleans)
		return count
	res = robotRangeBacktraceCore(0, 0, rows, cols, threshold, booleans)
	return res

#测试数据
print(robotRangeBacktrace(5,5,7))

面试题14:剪绳子

题目:给你一根长度为n的绳子,请把绳子剪成m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],……,k[n]。请问k[0]×k[1]×……×k[n]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

#递归+贪婪法
def cutRope(n):
	if n <= 1:
		return 0
	if n == 2:
		return 1
	if n == 3:
		return 2
	def cutRopCore(n):
		if n <= 4:
			return n
		if n > 3:
			return 3 * cutRopCore(n - 3)
	if n > 3:
		return cutRopCore(n)

#动态规划法
def cutRopeDynamic(n):
	if n <= 1:
		return 0
	if n == 2:
		return 1
	if n == 3:
		return 2
	resList = [0 for i in range(n + 1)]
	resList[0] = 0
	resList[1] = 1
	resList[2] = 2
	resList[3] = 3
	for i in range(4, n + 1):
		resList[i] = 0
		for j in range(1, i // 2 + 1):
			if resList[j] * resList[i - j] > resList[i]:
				resList[i] = resList[j] * resList[i - j]
	return resList[n]

#测试数据
print(cutRope(9))
print(cutRopeDynamic(9))

面试题15:二进制中1的个数

题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如,把9表示成二进制1001,有2位是1。因此,如果输入9,则该函数输出2。

def numOfBinaryOne(n):
	count = 0
	num = 1
	digit = 0
	while num != 0:
		if (n & num) != 0:
			count += 1
		num = num << 1
		digit += 1
		#当num向左位移64位后,不管是不是0,都停止
		if digit > 64:
			break
	return count
	
#测试数据
print(numOfBinaryOne(1001))

面试题16:数值的整数次方

题目:实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。

def pow(x, n):
	if x == 0:
		return 0
	if n == 0:
		return 1
	res = 1
	flag = True
	if n < 0:
		flag = False
		n = -n
	if n % 2 == 0:
		res = pow(x, n >> 1) * pow(x, n >> 1)
	else:
		res = pow(x, n >> 1) * pow(x, n >> 1) * x 
	return res if flag else 1.0 / res

#测试数据	
print(pow(2.5, 2))

面试题17:打印从1到最大的n位数(答案:略)

题目:输入数字n,按顺序打印从1到最大的n位十进制数。比如输入3,则打印出1、2、3一直到最大的3位数999。

面试题18:删除链表的节点

题目一:在O(1)时间内删除链表节点。

给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点。链表节点与函数的定义如下:
struct ListNode
{
int m_nKey;
ListNode* m_pNext;
};

def deleteNode(head, deleteNode):
	if head == None or deleteNode == None:
		return
	if head == deleteNode:
		head = head.next
		deleteNode == None
		return
	if deleteNode.next != None:
		nextNode = deleteNode.next
		deleteNode.value = nextNode.value
		deleteNode.next = nextNode.next
		nextNode = None
		return
	else:
		nextNode = head.next
		while nextNode != deleteNode:
			nextNode = nextNode.next
		nextNode = None
		return
题目二:删除链表中重复的节点。

在一个排序的链表中,如何删除重复的节点?例如,在下图(a)中重复的节点被删除之后,链表如下图(b)所示。
(a) 1–>2–>3–>4–>5
(b) 1–>2–>5
注:(a) 一个有7个节点的链表;(b) 当重复的节点被删除之后,链表中只剩下3个节点。

class ListNode():
    def __init__(self, value, next=None):
        self.value = value
        self.next = next
        
def deleteDoubleNode(head):
    if head == None:
        return head
    newNode = head
    #去除从头部开始的重复节点
    while newNode.next != None and newNode.value == newNode.next.value:
        tmp = newNode.next.next
        if tmp != None and newNode.next.value == tmp.value:
            newNode = newNode.next
        else:
            newNode = tmp
            if newNode == None:
                break
    if newNode == None:
        return newNode
    head = newNode
    chongfu = head.next
    while chongfu != None:
        while chongfu.next != None and chongfu.value == chongfu.next.value:
            tmp = chongfu.next.next
            if tmp != None and chongfu.next.value == tmp.value:
                chongfu = chongfu.next
            else:
                chongfu = tmp
                if chongfu == None:
                    break
        newNode.next = chongfu
        newNode = newNode.next
        if newNode == None:
            return head
        chongfu = chongfu.next
    return head
a = ListNode(1)
b = ListNode(1)
c = ListNode(1)
d = ListNode(2)
e = ListNode(3)
f = ListNode(3)
g = ListNode(4)
h = ListNode(4)
i = ListNode(5)
a.next=b
b.next=c
c.next=d
d.next=e
e.next=f
f.next=g
g.next=h
h.next=i
m = deleteDoubleNode(a)
#print(m.value)
#print(m.next.value)
#打印结果:2,5

面试题19:正则表达式匹配

题目:请实现一个函数用来匹配包含 “·” 和 “*” 的正则表达式。模式中的字符 “·” 表示任意一个字符,而’ “*” 表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串 “aaa” 与模式 “a.a” 和 “ab*ac*a” 匹配,但与 “aa.a” 和 “ab*a” 均不匹配。

def regMatch(strs, pattern):
    lstr = len(strs)
    lpt = len(pattern)
    def regMatchFuZhu(strs, pattern, lstr, lpt, idxs, idxp):
        if (idxs == lstr and idxp == lpt) or \
            (idxs == lstr and idxp == lpt - 2 and pattern[idxp + 1] == '*'):
            return True
        if (idxs < lstr and idxp >= lpt) or (idxs >= lstr and idxp < lpt):
            return False
        # while idxs < lstr and idxp < lpt:
        if strs[idxs] == pattern[idxp] or pattern[idxp] == '.':
            if idxp < lpt - 1 and pattern[idxp + 1] == '*':
                return regMatchFuZhu(strs, pattern, lstr, lpt, idxs, idxp + 2) \
                    or regMatchFuZhu(strs, pattern, lstr, lpt, idxs + 1, idxp) \
                    or regMatchFuZhu(strs, pattern, lstr, lpt, idxs + 1, idxp + 2) 
            else:
                return regMatchFuZhu(strs, pattern, lstr, lpt, idxs + 1, idxp + 1)
        elif idxp < lpt - 1 and pattern[idxp + 1] == '*':
            return regMatchFuZhu(strs, pattern, lstr, lpt, idxs, idxp + 2)
        else:
            return False
        return False
    return regMatchFuZhu(strs, pattern, lstr, lpt, 0, 0)

#测试数据
print(regMatch('aaa', 'ab*ac*a'))

面试题20:表示数值的字符串(答案:略)

题目:请实现一个函数来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、“5e2”、“-123”、“3.1416"及”-1E-16"都表示数值,但"12e"、“1a3.14”、“1.2.3”、"±5"及"12e+5.4"都不是。

面试题21:调整数组顺序使奇数位于偶数前面

题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。

def adjustOddEven(arr):
	if arr == None or len(arr) <= 0:
		return
	lens = len(arr)
	i = 0
	j = lens - 1
	def isOdd(x):
		if x % 2 == 1:
			return True
		else:
			return False
	while i < j:
		if isOdd(arr[i]):
			i += 1
		elif not isOdd(arr[j]):
			j -= 1
		else:
			tmp = arr[i]^arr[j]
			arr[i] = tmp^arr[i]
			arr[j] = tmp^arr[i]
	return

arr = [1,2,3,4,5]
print(arr)
adjustOddEven(arr)
print(arr)

面试题22:链表中倒数第k个节点

题目:输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,他们的值依次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点。链表节点定义如下:
struct ListNode
{
int m_nKey;
ListNode* m_pNext;
};

#节点类定义
class ListNode():
	def __init__(self, value):
		self.value = value
		self.next = None
		
def lastKNode(head, k):
	if head == None or k < 1:
		return None
	lens = 1
	tmp = head
	while tmp.next != None:
		lens += 1
		tmp = tmp.next
	if lens < k:
		return None
	head1 = head
	head2 = head
	k -= 1
	while head2.next != None and k > 0:
		head2 = head2.next
		k -= 1
	while head2.next != None and head1.next != None:
		head2 = head2.next
		head1 = head1.next
	return head1

def lastKthNode(head, k):
    if head == None or k <= 0:
        raise Exception("输入参数不合法!")
    lens = 0
    newNode = head
    while newNode != None:
        lens += 1
        newNode = newNode.next
    if lens < k:
        raise Exception("输入的k超过了取值范围!")
    newk = lens - k
    newNode = head
    while newk > 0:
        newk -= 1
        newNode = newNode.next
        if newk == 0:
            break
    return newNode
#测试数据
head0 = ListNode(1)
head1 = ListNode(2)
head2 = ListNode(3)
head3 = ListNode(4)
head4 = ListNode(5)
head5 = ListNode(6)
head0.next=head1
head1.next=head2
head2.next=head3
head3.next=head4
head4.next=head5
print(lastKNode(head0, 3).value)

面试题23:链表中环的入口节点

题目:如果一个链表中包含环,如何找出环的入口节点?例如,在下图所示的链表中,环的入口节点是节点3。

		-------------
        ↓           ↑
1-->2-->3-->4-->5-->6
  3
 / \
4   6
 \ /
  5
#节点类定义
class ListNode():
	def __init__(self, value):
		self.value = value
		self.next = None
		
def entryNodeOfRing(head):
	if head == None:
		return None
	head1 = head
	head2 = head.next
	while head1 != head2 and head1 != None and head2 != None:
		head1 = head1.next
		head2 = head2.next
		if head2.next != None:
			head2 = head2.next
		if head1 == None or head2 == None:
			return None
	head1 = head1.next
	head2 = head2.next.next
	k = 1
	while head1 != head2:
		head1 = head1.next
		head2 = head2.next.next
		k += 1
	head3 = head
	head4 = head
	while k > 0:
		head4 = head4.next
		k -= 1
	while head3 != head4:
		head3 = head3.next
		head4 = head4.next
	return head3

#测试数据
head0 = ListNode(1)
head1 = ListNode(2)
head2 = ListNode(3)
head3 = ListNode(4)
head4 = ListNode(5)
head5 = ListNode(6)
head0.next=head1
head1.next=head2
head2.next=head3
head3.next=head4
head4.next=head5
head5.next=head2
print(entryNodeOfRing(head0).value)

面试题24:反转链表

题目:定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。链表节点定义如下:
struct ListNode
{
int m_nKey;
ListNode* m_pNext;
};

#节点类定义
class ListNode():
	def __init__(self, value):
		self.value = value
		self.next = None
#递归法		
def inverseListNodeRecurive(head):
	if head.next == None or head == None:
		return head
	nextNode = head.next
	newHead = inverseListNodeRecurive(nextNode)
	nextNode.next = head
	head.next = None
	return newHead

#循环法
def inverseListNodeLoop(head):
	if head == None or head.next == None:
		return head
	newHead = head
	nextNode = None
	while newHead != None:
		tmp = newHead
		if newHead.next != None:
			newHead = newHead.next
		else:
			tmp.next = nextNode
			return newHead
		tmp.next = nextNode
		nextNode = tmp
	return newHead

#循环法2
def inverseListNodeLoop2(head):
	if head == None or head.next == None:
		return head
	newHead = None
	pre = None
	while head != None:
		next = head.next
		if next == None:
			newHead = head
		head.next = pre
		pre = head
		head = next
	return newHead

#测试数据
head0 = ListNode(1)
head1 = ListNode(2)
head2 = ListNode(3)
head0.next=head1
head1.next=head2

print(inverseListNodeRecurive(head0).value)
print(inverseListNodeRecurive(head0).next.value)
print(inverseListNodeLoop(head0).value)
print(inverseListNodeLoop(head0).next.value)

面试题25:合并两个排序的链表

题目:输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。例如,输入下图中的链表1和链表2,则合并之后的升序链表如链表3所示。链表节点定义如下:
struct ListNode
{
int m_nValue;
ListNode* m_pNext;
};
链表1:1–>3–>5–>7
链表2:2–>4–>6–>8
链表3:1–>2–>3–>4–>5–>6–>7–>8

#节点类定义
class ListNode():
	def __init__(self, value):
		self.value = value
		self.next = None
		
def mergeNodeList(head1, head2):
	if head1 == None:
		return head2
	if head2 == None:
		return head1
	newHead = None
	if head1.value < head2.value:
		newHead = head1
		newHead.next = mergeNodeList(head1.next, head2)
	else:
		newHead = head2
		newHead.next = mergeNodeList(head1, head2.next)
	return newHead
#测试数据
h1 = ListNode(1)
m1 = ListNode(7)
t1 = ListNode(12)
h1.next = m1
m1.next = t1
h2 = ListNode(2)
m2 = ListNode(3)
t2 = ListNode(12)
h2.next = m2
m2.next = t2

h = mergeNodeList(h1, h2)
print(h.value)
print(h.next.value)
print(h.next.next.value)

面试题26:树的子结构

题目:输入两棵二叉树A和B,判断B是不是A的子结构。二叉树节点的定义如下:
struct BinaryTreeNode
{
double m_dbValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
如下图:B是A的子结构

    A      B
    8      8
   / \    / \
  8   7  9   2
 / \
9   2
   / \
  4   7
def hasSubtree(bigTree, smallTree):
	if bigTree == None:
		return False
	if smallTree == None:
		return True
	def hasSubtreeFuzhu(bigTree, smallTree):
		if smallTree == None:
			return True
		if bigTree == None or bigTree.value != smallTree.value:
			return False
		else:
			return hasSubtreeFuzhu(bigTree.left, smallTree.left) \
			and hasSubtreeFuzhu(bigTree.right, smallTree.right)
	flag = False
	if bigTree.value == smallTree.value and flag == False:
		flag = hasSubtreeFuzhu(bigTree, smallTree)
	if flag == False:
		flag = hasSubtree(bigTree.left, smallTree) or hasSubtree(bigTree.right, smallTree)
	return flag

#测试数据
rootA = BinaryTreeNode(8)
l1 = BinaryTreeNode(8)
l2 = BinaryTreeNode(9)
l3 = BinaryTreeNode(4)
r1 = BinaryTreeNode(7)
r2 = BinaryTreeNode(2)
r3 = BinaryTreeNode(7)
rootA.left = l1
rootA.right = r1
l1.left = l2
l1.right = r2
r2.left = l3
r2.right = r3
rootB = BinaryTreeNode(8)
lb1 = BinaryTreeNode(9)
rb1 = BinaryTreeNode(2)
rootB.left = lb1
rootB.right = rb1
print(hasSubtree(rootA, rootB))

面试题27:二叉树的镜像

题目:请完成一个函数,输入一棵二叉树,该函数输出它的镜像。二叉树节点的定义如下:
struct BinaryTreeNode
{
int m_dbValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
如下图所示,两棵二叉树互为镜像。

     8             8
   /   \         /   \
  6    10      10     6
 / \   / \     / \   / \
5   7 9  11   11  9 7   5 
#二叉树节点类定义
class BinaryTreeNode():
	def __init__(self, value, left = None, right = None):
		self.value = value
		self.left = left
		self.right = right
		
def mirrorBinaryTree(root):
	if root == None or (root.left == None and root.right == None):
		return
	tmp = root.left
	root.left = root.right
	root.right = tmp
	mirrorBinaryTree(root.left)
	mirrorBinaryTree(root.right)
	return

#测试数据
rootA = BinaryTreeNode(8)
l1 = BinaryTreeNode(8)
l2 = BinaryTreeNode(9)
l3 = BinaryTreeNode(4)
r1 = BinaryTreeNode(7)
r2 = BinaryTreeNode(2)
r3 = BinaryTreeNode(7)
rootA.left = l1
rootA.right = r1
l1.left = l2
l1.right = r2
r2.left = l3
r2.right = r3
#     A  
#     8  
#    / \ 
#   8   7
#  / \
# 9   2
#    / \
#   4   7
mirrorBinaryTree(rootA)
print(rootA.right.left.left.value)
print(rootA.right.left.right.value)

面试题28:对称的二叉树

题目:请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。例如,在下图28-1中的三棵二叉树中,第一课二叉树是对称的,而另外两棵不是。

图28-1
     8            8            7     
   /   \        /   \        /   \   
  6     6      6     9      7     7  
 / \   / \    / \   / \    / \   /  
5   7 7   5  5   7 7   5  7   7 7 
#二叉树节点类定义
class BinaryTreeNode():
	def __init__(self, value, left = None, right = None):
		self.value = value
		self.left = left
		self.right = right
def isSymmetricBinaryTree(root):
	def isSymmettical(treeNode1, treeNode2):
		if treeNode1 == None and treeNode2 == None:
			return True
		if treeNode1 == None or treeNode2 == None:
			return False
		if treeNode1.value != treeNode2.value:
			return False
		else:
			return isSymmettical(treeNode1.left, treeNode2.right) and \
				   isSymmettical(treeNode1.right, treeNode2.left)
	return isSymmettical(root, root)
	
#测试数据
#      8      
#    /   \    
#   6     6   
#  / \   / \  
# 5   7 7   5 
rootA = BinaryTreeNode(8)
l1 = BinaryTreeNode(6)
l2 = BinaryTreeNode(5)
l3 = BinaryTreeNode(7)
r1 = BinaryTreeNode(6)
r2 = BinaryTreeNode(5)
r3 = BinaryTreeNode(7)
rootA.left = l1
rootA.right = r1
l1.left = l2
l1.right = r3
r1.left = l3
r1.right = r2
print(isSymmetricBinaryTree(rootA))

面试题29:顺时针打印矩阵(答案:略)

题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。例如,如果输入如下矩阵:

1234
5678
9101112
13141516
则依次打印出数字:1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10。

面试题30:包含min函数的栈(答案:略)

题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min、push及pop的时间复杂度都是O(1)。

面试题31:栈的压入、弹出序列

题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列{1,2,3,4,5}是某栈的压栈序列,序列{4,5,3,2,1}是该压栈序列对应的一个弹出序列,但{4,3,5,1,2}就不可能是该压栈序列的弹出序列。

#定义栈
class Stack(object):
	def __init__(self):
		self.stack = []

	def push(self, data):
		self.stack.append(data)

	def pop(self):
		if self.stack:
			return self.stack.pop()
		else:
			raise IndexError('pop from an empty stack')

	def peek(self):
		if self.stack:
			return self.stack[-1]
		else:
			raise IndexError('stack is empty!')
	
	def isEmpty(self):
		return not self.stack

	def size(self):
		return len(self.stack)

#测试栈用数据
stack = Stack()
stack.push(5)
stack.push(4)
stack.push(3)
print(stack.stack)
print(stack.pop())
print(stack.pop())
print(stack.peek())

#正解
def isPopOrder(pushList, popList):
	if pushList == None or popList == None or \
		len(pushList) == 0 or len(popList) == 0 or len(pushList) != len(popList):
		return False
	stack = Stack()
	idx = 0
	for data in pushList:
		stack.push(data)
		while not stack.isEmpty() and stack.peek() == popList[idx]:
			stack.pop()
			idx += 1
	return stack.isEmpty()

#测试数据
print(isPopOrder([1,2,3,4,5], [4,5,3,2,1]))

面试题32:从上到下打印二叉树

题目一:不分行从上到下打印二叉树

从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。例如,输入下图(32-1)中的二叉树,则依次打印出8,6,10,5,7,9,11。二叉树节点的定义如下:
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};

图32-1
     8
   /   \
  6     10
 / \    / \
5   7  9  11
#二叉树节点类定义
class BinaryTreeNode():
	def __init__(self, value, left = None, right = None):
		self.value = value
		self.left = left
		self.right = right
#队列类定义
class Queue():
	def __init__(self):
		self.queue = []

	def addTail(self, data):
		self.queue.append(data)

	def pollHead(self):
		if self.queue:
			return self.queue.pop(0)
		else:
			raise IndexError('poll from an empty queue')

	def peek(self):
		if self.queue:
			return self.queue[0]
		else:
			raise IndexError('queue is empty!')
	
	def isEmpty(self):
		return not self.queue

	def size(self):
		return len(self.queue)

def pirntBinaryTreeNodeFromLeftToRight(root):
    if root == None:
        return
    arr = []
    arr.append(root)
    while len(arr) > 0:
        tmp = arr.pop(0)
        if tmp.left != None:
            arr.append(tmp.left)
        if tmp.right != None:
            arr.append(tmp.right)
        print(tmp.value, end =' ')
    print()
    return

#测试数据
#      8      
#    /   \    
#   6     10   
#  / \   / \  
# 5   7 9   11 
rootA = BinaryTreeNode(8)
l1 = BinaryTreeNode(6)
l2 = BinaryTreeNode(5)
l3 = BinaryTreeNode(9)
r1 = BinaryTreeNode(10)
r2 = BinaryTreeNode(11)
r3 = BinaryTreeNode(7)
rootA.left = l1
rootA.right = r1
l1.left = l2
l1.right = r3
r1.left = l3
r1.right = r2
pirntBinaryTreeNodeFromLeftToRight(rootA)
题目二:分行从上到下打印二叉树。

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。例如,打印上图(32-1)中的二叉树的结果为:
8
6 10
5 7 9 11

def pirntBinaryTreeNodeFromLeftToRightByRow(root):
    if root == None:
        return 
    arr = [root]
    nextLevel = 0
    toBePrint = 1
    while len(arr) > 0:
        tmp = arr.pop(0)
        if tmp.left != None:
            nextLevel += 1
            arr.append(tmp.left)
        if tmp.right != None:
            nextLevel += 1
            arr.append(tmp.right)
        print(tmp.value, end = ' ')
        toBePrint -= 1
        if toBePrint == 0:
            print()
            toBePrint = nextLevel
            nextLevel = 0
    return
	
#测试数据(如题目一)
pirntBinaryTreeNodeFromLeftToRightByRow(rootA)
题目三:之字形打印二叉树

请实现一个函数,按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。例如,按之字形打印下图(图32-3)中二叉树的结果为:

1
3	2
4	5	6	7
15	14	13	12	11	10	9	8
图32-3
           1
      /         \
     2           3
   /   \       /   \
  4     5     6     7
 / \   / \   / \   / \
8   9 10 11 12 13 14 15
def pirntBinaryTreeNodeFromLeftToRightByZigzag(root):	
    if root == None:
        return
    arr1 = [root]
    arr2 = []
    nextLevel = 0
    toBePrint = 1
    flag = True
    while len(arr1) > 0 or len(arr2) > 0:
        if flag:
            while len(arr1) > 0:
                tmp = arr1.pop()
                if tmp.left != None:
                    nextLevel += 1
                    arr2.append(tmp.left) 
                if tmp.right != None:
                    nextLevel += 1
                    arr2.append(tmp.right)
                print(tmp.value, end = ' ')
                toBePrint -= 1
                if toBePrint == 0:
                    print()
                    toBePrint = nextLevel
                    nextLevel = 0
                    flag = not flag
        else:
            while len(arr2) > 0:
                tmp = arr2.pop()
                if tmp.right != None:
                    nextLevel += 1
                    arr1.append(tmp.right)
                if tmp.left != None:
                    nextLevel += 1
                    arr1.append(tmp.left) 
                print(tmp.value, end = ' ')
                toBePrint -= 1
                if toBePrint == 0:
                    print()
                    flag = not flag
                    toBePrint = nextLevel
                    nextLevel = 0
    return

#测试数据
#            1
#       /         \
#      2           3
#    /   \       /   \
#   4     5     6     7
#  / \   / \   / \   / \
# 8   9 10 11 12 13 14 15
rootB = BinaryTreeNode(1)
l1_1 = BinaryTreeNode(2)
r1_1 = BinaryTreeNode(3)
l2_1 = BinaryTreeNode(4)
l2_2 = BinaryTreeNode(6)
r2_1 = BinaryTreeNode(5)
r2_2 = BinaryTreeNode(7)
l3_1 = BinaryTreeNode(8)
l3_2 = BinaryTreeNode(10)
l3_3 = BinaryTreeNode(12)
l3_4 = BinaryTreeNode(14)
r3_1 = BinaryTreeNode(9)
r3_2 = BinaryTreeNode(11)
r3_3 = BinaryTreeNode(13)
r3_4 = BinaryTreeNode(15)
rootB.left = l1_1
rootB.right = r1_1
l1_1.left = l2_1
l1_1.right = r2_1
r1_1.left = l2_2
r1_1.right = r2_2
l2_1.left = l3_1
l2_1.right = r3_1
r2_1.left = l3_2
r2_1.right = r3_2
l2_2.left = l3_3
l2_2.right = r3_3
r2_2.left = l3_4
r2_2.right = r3_4
pirntBinaryTreeNodeFromLeftToRightByZigzag(rootB)

面试题33:二叉搜索树的后序遍历序列

题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同。例如,输入数组{5,7,6,9,11,10,8},则返回true,因为这个整数序列是下图(图33)二叉搜索树的后序遍历结果。如果输入的数组是{7,4,6,5},则由于没有哪棵二叉搜索树的后序遍历结果是这个序列,因此返回false。

图33
     8
   /   \
  6     10
 / \    / \
5   7  9  11
#二叉树节点类定义
class BinaryTreeNode():
	def __init__(self, value, left = None, right = None):
		self.value = value
		self.left = left
		self.right = right
		
def isPostOrderResultOfBinaryTree(arr):
	if arr == None or len(arr) <= 0:
		return False
	def isPostOrderResultOfBinaryTreeFuZhu(arr, start, end):
		if arr == None or end <= 0:
			return False
		restart = 0
		for i in range(start, end):
			if arr[i] > arr[end]:
				restart = i
				break
		for j in range(restart, end):
			if arr[j] < arr[end]:
				return False
		left = True
		if start < restart - 1:
			left = isPostOrderResultOfBinaryTreeFuZhu(arr, start, restart - 1)
		right = True
		if restart < end - 1:
			right = isPostOrderResultOfBinaryTreeFuZhu(arr, restart, end - 1)
		return left and right
	return isPostOrderResultOfBinaryTreeFuZhu(arr, 0, len(arr) - 1)
	
def isPostorder(ls):
    if len(ls) <= 0 or ls == None:
        return True
    mid = ls[-1]
    idx = 0
    for i in range(len(ls)):
        if ls[i] > mid:
            idx = i
            break
    print("idx: %s" %idx)
    left = ls[: idx]
    right = ls[idx: -1]
    for s in right:
        if s < mid:
            return False
    return isPostorder(left) and isPostorder(right)
#测试数据
#      8
#    /   \
#   6     10
#  / \    / \
# 5   7  9  11
arr = [5,7,6,9,11,10,8]
arr = [7,4,6,5]
print(isPostOrderResultOfBinaryTree(arr))

面试题34:二叉树中和为某一值的路径

题目:输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。二叉树节点的定义如下:
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};

图34
   10
   / \
  5  12
 / \
4   7

图34中,二叉树中有两条和为22的路径:一条路径经过节点10、5、7;另一条路径经过节点10、12。

#二叉树节点类定义
class BinaryTreeNode():
	def __init__(self, value, left = None, right = None):
		self.value = value
		self.left = left
		self.right = right
		
def findPath(root, target):
	if root == None:
		return None
	def findPathFuZhu(root, target, res, ls):
		if root == None:
			return res
		ls.append(root.value)
		target -= root.value
		if target == 0 and root.left == None and root.right == None:
			newLs = [i for i in ls]
			res.append(newLs)
		if target > 0:
			findPathFuZhu(root.left, target, res, ls)
			findPathFuZhu(root.right, target, res, ls)
		if target < 0:
			return res
		# ls.pop() == del(ls[-1])
		del(ls[-1])
		return res
	res = []
	ls = []
	res = findPathFuZhu(root, target, res, ls)
	return res

#测试数据
#    10
#    / \
#   5  12
#  / \
# 4   7
rootB = BinaryTreeNode(10)
l1_1 = BinaryTreeNode(5)
r1_1 = BinaryTreeNode(12)
l2_1 = BinaryTreeNode(4)
r2_1 = BinaryTreeNode(7)
rootB.left = l1_1
rootB.right = r1_1
l1_1.left = l2_1
l1_1.right = r2_1

面试题35:复杂链表的复制

题目:请实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表。在复杂链表中,每个节点除了有一个m_pNext指针指向下一个节点,还有一个m_pSibling指针指向链表中的任意节点或者nullptr。节点的C++定义如下:
struct ComplexListNode
{
int m_nValue;
ComplexListNode* m_pNext;
ComplexListNode* m_pSibling;
}

A
B
C
D
E
    ---------
    ↓       ↑
A-->B-->C-->D-->E
↓   |   ↑       ↑
----|----       |
    ↓           |
    -------------
#定义复杂链表节点类
class ComplexListNode():
    def __init__(self, value, next=None, sibling=None):
        self.value = value
        self.next = next
        self.sibling = sibling
        
def copyComplexListNode(head):
	if head == None:
		return
	def cloneNodes(head):
		if head == None:
			return
		node = head
		while node != None:
			newNode = ComplexListNode(node.value)
			nextNode = node.next
			node.next = newNode
			newNode.next = nextNode
			node = nextNode
		return
	def addSiblingNodes(head):
		if head == None:
			return
		node = head
		i = 0
		while node != None:
			if i % 2 == 0:
				siblingNode = node.sibling
				if siblingNode != None:
					node.next.sibling = siblingNode.next
			i += 1
			node = node.next
		return
	def splitNodeList(head):
		if head == None:
			return
		oldHead = head
		newHead = head.next
		oldTmp = oldHead
		newTmp = newHead
		while oldTmp != None and newTmp != None:
			oldTmp.next = newTmp.next
			oldTmp = oldTmp.next
			if oldTmp != None:
				newTmp.next = oldTmp.next
				newTmp = newTmp.next
		return [oldHead, newHead]
	cloneNodes(head)
	addSiblingNodes(head)
	return splitNodeList(head)

#测试数据
a = ComplexListNode(1)
b = ComplexListNode(2)
c = ComplexListNode(3)
d = ComplexListNode(4)
e = ComplexListNode(5)
a.next = b
b.next = c
c.next = d
d.next = e

a.sibling = c
b.sibling = e
d.sibling = b

oldAndNew = copyComplexListNode(a)
d = oldAndNew[0]
while d != None:
	print(d.value)
	if d.sibling != None:
		print('sibling.value: %s' %d.sibling.value)
	d = d.next

面试题36:二叉搜索树与双向链表

题目:输入一个二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的节点,只能调整树中节点指针的方向。比如,输入下图(图36-1)中左边的二叉搜索树,则输出转换之后的排序双向链表。二叉树的节点定义如下:
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};

图36-1
     10
   /    \
  6     14   -->  4==6==8==10==12==14==16
 / \    / \
4   8 12   16
#定义二叉树节点
class BinaryTreeNode():
    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right

def convertBinaryTreeToListNode(root):
    last = None
    def turnBinaryTreeToListNode(root, last):
        if root == None:
            return root
        current = root
        if current.left != None:
            last = turnBinaryTreeToListNode(current.left, last)
        current.left = last
        if last != None:
            last.right = current
        last = current
        if current.right != None:
            last = turnBinaryTreeToListNode(current.right, last)
        return last
    newHead = turnBinaryTreeToListNode(root, last)
    while newHead.left != None:
        newHead = newHead.left
    return newHead
#    10
#    / \
#   5  12
#  / \
# 4   7
rootB = BinaryTreeNode(10)
l1_1 = BinaryTreeNode(5)
r1_1 = BinaryTreeNode(12)
l2_1 = BinaryTreeNode(4)
r2_1 = BinaryTreeNode(7)
rootB.left = l1_1
rootB.right = r1_1
l1_1.left = l2_1
l1_1.right = r2_1

newHead = convertBinaryTreeToListNode(rootB)
while newHead != None:
  print(newHead.value)
  newHead = newHead.right

面试题37:序列化二叉树

题目:请实现两个函数,分别用来序列化和反序列化二叉树。
序列化规则:根据前序遍历的顺序来序列化二叉树,因为前序遍历是从根节点开始的。在遍历二叉树碰到nullptr指针时,这些nullptr指针序列化为一个特殊的字符(如’$‘)。另外,节点的数值之间要用一个特殊字符(如’,')隔开。
根据这样的序列化规则,则下图(图37-1)中的二叉树被序列化成字符串"1,2,4,$,$,$,3,5,$,$,6,$,$"。

图37-1
    1
   / \
  2   3
 /   / \
4   5   6
#定义二叉树节点
class BinaryTreeNode():
    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right
        
#序列化函数
def serializeBinaryTree(root):
	if root == None:
		return '$,$'
	def serializeBinaryTreeSub(root, rlt):
		if root == None:
			rlt += '$,'
			return rlt
		rlt += str('%s,' %root.value)
		rlt = serializeBinaryTreeSub(root.left, rlt)
		rlt = serializeBinaryTreeSub(root.right, rlt)
		return rlt
	rlt = serializeBinaryTreeSub(root, '')
	return rlt[: -1]

#测试数据
#    10
#    / \
#   5  12
#  / \
# 4   7
rootB = BinaryTreeNode(10)
l1_1 = BinaryTreeNode(5)
r1_1 = BinaryTreeNode(12)
l2_1 = BinaryTreeNode(4)
r2_1 = BinaryTreeNode(7)
rootB.left = l1_1
rootB.right = r1_1
l1_1.left = l2_1
l1_1.right = r2_1
rlt = serializeBinaryTree(rootB)
print(rlt)

#反序列化函数
def deserializeBinaryTree(strs):
	if strs == None or len(strs) <= 0 or strs == '$':
		return None
	queue = Queue()
	ls = strs.split(',')
	for s in ls:
		if s != ',':
			queue.addTail(s)
	def deserializeBinaryTreeSub(queue):
		if queue.isEmpty():
			return None
		value = str(queue.pollHead())
		root = None
		if (value != '$'):
			root = BinaryTreeNode(value)
			root.left = deserializeBinaryTreeSub(queue)
			root.right = deserializeBinaryTreeSub(queue)
		return root
	root = deserializeBinaryTreeSub(queue)
	return root

#测试数据
root = deserializeBinaryTree('10,5,4,$,$,7,$,$,12,$,$')
print(root.value)
print(root.left.value)
print(root.left.left.value)
print(root.left.right.value)

面试题38:字符串的排列

题目:输入一个字符串,打印出该字符串中字符的所有排列。例如,输入字符串abc,则打印出由字符a、b、c所能排列出来的所有字符串abc、acb、bca、cab和cba。
扩展:获得字符串的所有组合,例如输入字符串,则其组合包括’a’,‘b’,‘c’,‘ab’,‘ac’,‘bc’,‘abc’。

def printFullPermutation(strs):
	if strs == None or len(strs) <= 0:
		return
	ls = [s for s in strs]
	def printFullPermutationSub(ls, idx):
		if ls == None or len(ls) <= 0:
			return
		if idx < 0 or idx > len(ls):
			raise Exception("输入参数不合法!")
		#以下为核心代码
		if idx == len(ls):
			print(''.join(ls))
		for i in range(idx, len(ls)):
			if i == idx or ls[i] == ls[idx]:
				printFullPermutationSub(ls, idx + 1)
				continue
			exchange(ls, i, idx)
			printFullPermutationSub(ls, idx + 1)
			exchange(ls, i, idx)
		return
	def exchange(ls, i, j):
		a = ls[i]
		ls[i] = ls[j]
		ls[j] = a
		return
	printFullPermutationSub(ls, 0)
	return

#测试数据
ls = [s for s in 'abc']
printFullPermutation(ls)

#扩展
def getAllCombination(strs):
	result = []
	if strs == None or len(strs) <= 0:
		return result
	def getAllCombinationSub(ls, m, res, result):
		if m == 0:
			result.append(''.join(res))
			return
		if len(ls) > 0:
			res.append(ls[0])
			getAllCombinationSub(ls[1:], m - 1, res, result)
			res.pop()
			getAllCombinationSub(ls[1:], m, res, result)
	ls = [s for s in strs]
	for i in range(1, len(ls) + 1):
		res = []
		getAllCombinationSub(ls, i, res, result)
	return result

#测试数据
print(getAllCombination('abc'))

面试题39:数组中出现次数超过一半的数字

题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如,输入一个长度为9的数组{1,2,3,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。

def MoreThanHalf(arr):
	if arr == None or len(arr) <= 0:
		raise Exception("输入参数不合法!")
	tmp = [0, 0]
	for i in arr:
		if tmp[1] == 0:
			tmp[0] = i
			tmp[1] = 1
		elif tmp[0] == i:
			tmp[1] += 1
		else:
			tmp[1] -= 1
	res = tmp[0]
	num = 0
	for i in arr:
		if res == i:
			num += 1
	if num > (len(arr) >> 1):
		print(res)
		return res
	else:
		raise Exception("没有符合条件的值!")

#测试数据
MoreThanHalf([1,1,2,1,1,3,3])

面试题40:最小的k个数(答案:略)

题目:输入n个整数,找出其中最小的k个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

面试题41:数据流中的中位数(答案:略)

题目:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。

面试题42:连续子数组的最大和

题目:输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。
例如,输入的数组为{1,-2,3,10,-4,7,2,-5},和最大的子数组为{3,10,-4,7,2},因此输出为该子数组的和18。

def maxSumOfSubarrays(arr):
	if arr == None or len(arr) <= 0:
		raise Exception("输入参数不合法!")
	import sys
	rlt = -sys.maxsize
	current = 0
	rltArr = []
	currentArr = []
	for a in arr:
		if current + a < a:
			current = a
			currentArr = [a]
		else:
			current += a
			currentArr.append(a)
		if rlt < current:
			rlt = current
			rltArr = [a for a in cuurentArr]
	print(rlt)
	return rlt

#测试数据
maxSumOfSubarrays([1,-2,3,10,-4,7,2,-5])

面试题43:1~n整数中1出现的次数

题目:输入一个整数n,求1~n这n个整数的十进制表示中1出现的次数。例如,输入12,1~12这些整数中包含1的数字有1、10、11和12,1一共出现了5次。

#方法一
def numberOfOne(n):
	if n == None or n <= 0:
		return 0
	num = 0
	def numberOfOneSub(n):
		num = 0
		while n > 0:
			tmp = n - n // 10 * 10
			if tmp == 1:
				num += 1
			n = n // 10
		return num
	for i in range(1, n + 1):
		num += numberOfOneSub(i)
	return num

#测试数据
print(numberOfOne(1000))

#方法二,利用全排列
def numberOfOneF(n):
	if n == None or n <= 0:
		return 0
	def fenjie(n):
		'''
			将一个大于10的整数分解为最大位数保留,其他位数全为0,再减去1.及最大位数的值,及其对应的位数。
			例如:fenjie(1000) = 999
			例如:fenjie(3521) = 2999
		'''
		if n < 0:
			raise Exception("输入参数不合法!")
		if n <= 9:
			return (n, -1, 0)
		num = 0
		while n > 9:
			n //= 10
			num += 1
		if n == 1:
			return (n * 10 ** num - 1, 9, num - 1)
		else:
			return (n * 10 ** num - 1, n - 1, num)
	num = 0
	while n > 0:
		tmp = fenjie(n)
		num += 10 ** tmp[2] + (tmp[1] + 1) * 10 ** (tmp[2] - 1) * tmp[2]
		n -= tmp[0]
	return int(num)
	
#测试数据
print(numberOfOneF(1000))
print(numberOfOneF(7032572))
7032572 == 6999999 + 29999 + 1999 + 499 + 69 + 7
print(1000000 + 700000 * 6 + 10000 + 3000 * 4 + 1000 + 200 * 3 + 100 + 50 * 2 + 10 + 7 * 1 + 1)

面试题44:数字序列中某一位的数字

题目:数字以0123456789101112131415···的格式序列化到一个字符序列中。在这个序列中,第5位(从0开始计数)是5,第13位是1,第19位是4,等等。请写一个函数,求任意第n位对应的数字。

def digitAtIndex(n):
	if n <= 10:
		return n - 1
	weishu = 2
	n = n - 10
	while n - weishu * (9 * 10 ** (weishu - 1)) > 0:
		n -= weishu * (9 * 10 ** (weishu - 1))
		weishu += 1
	geshu = n // weishu
	yushu = n % weishu
	value = 10 ** (weishu - 1) + geshu - 1
	rlt = -1
	if yushu == 0:
		rlt = str(value)[-1]
	else:
		rlt = str(value + 1)[yushu - 1]
	print(rlt)
	return rlt

#测试数据
# 0-9:10
# 10-99:2*90
# 100-999:3*900
# 1000-9999:4*9000

digitAtIndex(190)
digitAtIndex(191)
digitAtIndex(2890)

面试题45:把数组排成最小的数

题目:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如,输入数组{3,32,321},则打印出这3个数字能排成的最小数字321323。

def getMinNumOfRange(arr):
    if arr == None or len(arr) <= 0:
        raise Exception("输入参数不合法!")
    def simulationQuickSort(arr):
        if arr == None or len(arr) <= 0:
            raise Exception("输入参数不合法!")
        first = 0
        last = len(arr) - 1
        def compareStr(m, n):
            mn = '%s%s' %(m, n)
            nm = '%s%s' %(n, m)
            flag = True
            for i,j in zip(mn, nm):
                if i < j:
                    break
                elif i == j:
                    continue
                else:
                    flag = False
                    break
            return flag
        def simulationQuickSortSub(arr, first, last):
            if arr == None or first >= last:
                return
            base = arr[first]
            start = first
            end = last
            while start < end:
                if compareStr(base, arr[end]):
                    end -= 1
                elif compareStr(arr[start], base):
                    start += 1
                else:
                    tmp = arr[start]
                    arr[start] = arr[end]
                    arr[end] = tmp
            arr[first] = arr[start]
            arr[start] = base
            simulationQuickSortSub(arr, first, start - 1)
            simulationQuickSortSub(arr, start + 1, last)
        simulationQuickSortSub(arr, first, last)
    simulationQuickSort(arr)
    print(''.join(map(str,arr)))

#测试数据
arr = [3,32,321]
getMinNumOfRange(arr)

面试题46:把数字翻译成字符串

题目:给定一个数字,我们按照如下规则把它翻译为字符串:0翻译成"a",1翻译成"b",……,11翻译成"l",……,25翻译成"z"。一个数字可能有多个翻译。例如,12258有5种不同的翻译,分别是"bccfi"、“bwfi”、“bczi”、“mcfi"和"mzi”。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。

def numOfMethodsTranslateDigitsToliteral(n):
	if n == None or n < 0:
		raise Exception("输入参数不合法!")
	strs = str(n)
	lens = len(strs)
	def fuzhu(strs, lens, idx):
		if idx >= lens:
			return 1
		if strs[idx] == '0' or strs[idx] >= '3':
			return fuzhu(strs, lens, idx + 1)
		elif strs[idx] == '1':
			if idx < lens - 1:
				return fuzhu(strs, lens, idx + 1) + fuzhu(strs, lens, idx + 2)
			else:
				return fuzhu(strs, lens, idx + 1)
		else:
			if idx < lens - 1 and strs[idx + 1] < '6':
				return fuzhu(strs, lens, idx + 1) + fuzhu(strs, lens, idx + 2)
			else:
				return fuzhu(strs, lens, idx + 1)
	print(fuzhu(strs, lens, 0))
	return fuzhu(strs, lens, 0)

#测试数据
numOfMethodsTranslateDigitsToliteral(12258)

#方法二
def translateNumToStr(strN):
    arr = []
    lens = len(strN)
    def fuZhu(strN, arr, res, idx, lens):
        if idx >= lens:
            arr.append(''.join(res))
            return
        if strN[idx] in ['0', '1'] or (strN[idx] == '2' and idx + 1 < lens and strN[idx + 1] <= '5'):
            if idx + 1 < lens:
                res.append(chr(ord('a') + int(strN[idx])))
                fuZhu(strN, arr, res, idx + 1, lens)
                res.pop()
                res.append(chr(ord('a') + int(strN[idx: idx + 2])))
                fuZhu(strN, arr, res, idx + 2, lens)
                res.pop()
            else:
                res.append(chr(ord('a') + int(strN[idx])))
                fuZhu(strN, arr, res, idx + 1, lens) 
                res.pop()
        else:
            res.append(chr(ord('a') + int(strN[idx])))
            fuZhu(strN, arr, res, idx + 1, lens)
            res.pop()
        return
    fuZhu(strN, arr, [], 0, lens)
    print(arr) 
    return len(arr)          

#测试数据
translateNumToStr('12258')

面试题47:礼物的最大价值

题目:在一个m×n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向左或者向下移动一格,直到到达棋盘的右下角。给定一个棋盘及其上面的礼物,请计算你最多能拿到多少价值的礼物?
例如,在下面的棋盘中,如果沿着带下划线的数字的线路(1、12、5、7、7、16、5),那么我们能拿到最大价值为53的礼物。

11038
12296
57411
37165
#方法一
def maxValueOfGift(gifts):
	if gifts == None:
		return 0
	import numpy as np
	rows = np.shape(gifts)[0]
	cols = np.shape(gifts)[1]
	if rows <=0 or cols <= 0:
		return 0
	values = [[0 for i in range(rows)] for j in range(cols)]
	values[0][0] = gifts[0][0]
	for i in range(1, rows):
		values[0][i] = gifts[0][i] + values[0][i - 1]
	for j in range(1, cols):
		values[j][0] = gifts[j][0] + values[j - 1][0]
	for i in range(1, rows):
		for j in range(1, cols):
			values[i][j] = gifts[i][j] + max(values[i - 1][j], values[i][j - 1])
	return values[rows - 1][cols - 1]

#方法二
def maxValueOfGift2(gifts):
	if gifts == None:
		return 0
	import numpy as np
	rows = np.shape(gifts)[0]
	cols = np.shape(gifts)[1]
	if rows <=0 or cols <= 0:
		return 0
	values = [0 for i in range(cols)]
	for row in range(0, rows):
		for col in range(0, cols):
			up = 0
			left = 0
			if row > 0:
				up = values[col]
			if col > 0:
				left = values[col - 1]
			values[col] = gifts[row][col] + max(up, left)
	return values[cols - 1] 

#测试数据
gifts = [[0 for i in range(4)] for j in range(4)]
gifts[0][0] = 1
gifts[0][1] = 10
gifts[0][2] = 3
gifts[0][3] = 8
gifts[1][0] = 12
gifts[1][1] = 2
gifts[1][2] = 9
gifts[1][3] = 6
gifts[2][0] = 5
gifts[2][1] = 7
gifts[2][2] = 4
gifts[2][3] = 11
gifts[3][0] = 3
gifts[3][1] = 7
gifts[3][2] = 16
gifts[3][3] = 5
print(maxValueOfGift(gifts))
print(maxValueOfGift2(gifts))

面试题48:最长不含重复字符的子字符串

题目:请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。假设字符串中只包含’a’~'z’的字符。例如,在字符串"arabcacfr"中,最长的不含重复字符的子字符串是"acfr",长度为4。

def maxNoRepeatSubStr(strs):
	rlt = ''
	tmp = ''
	for s in strs:
		if s not in tmp:
			tmp += s
		else:
			idx = tmp.index(s)
			tmp = tmp[idx + 1:]
			tmp += s
		if len(tmp) >= len(rlt):
			rlt = tmp
	print('substr: %s; lens: %s' %(rlt, len(rlt)))
	return rlt

maxNoRepeatSubStr('arabcacfr')
maxNoRepeatSubStr('abcdefg')

面试题49:丑数

题目:我们把只包含因子2、3和5的数称作丑数(Ugly Number)。求按从小到大的顺序的第1500个丑数。例如,6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当作第一个丑数。

def nthChoushu(n):
	if n <= 5:
		print(n)
		return n
	rltLs = [0 for i in range(n)]
	for i in range(1, 6):
		rltLs[i - 1] = i
	dicts = {2 : 0, 3 : 0, 5 : 0}
	for m in range(5, n):
		for i in range(dicts[2], m):
			if rltLs[i] * 2 > rltLs[m - 1]:
				dicts[2] = i
				break
		for j in range(dicts[3], m):
			if rltLs[j] * 3 > rltLs[m - 1]:
				dicts[3] = j
				break
		for k in range(dicts[5], m):
			if rltLs[k] * 5 > rltLs[m - 1]:
				dicts[5] = k
				break
		rltLs[m] = min(rltLs[dicts[2]] * 2, rltLs[dicts[3]] * 3, rltLs[dicts[5]] * 5)
	print(rltLs[n - 1])
	return rltLs[n - 1]

#测试数据
nthChoushu(1500)

面试题50:第一个只出现一次的字符

题目一:字符串中第一个只出现一次的字符。

在字符串中找出第一个只出现一次的字符。如输入"abaccdeff",则输出"b"。

def firstCharNotRepeat(strs):
	if strs == None or len(strs) <= 0:
		raise Exception("输入参数不合法!")
	dicts = {}
	rlt = ''
	for s in strs:
		dicts[s] = 0
	for s in strs:
		dicts[s] += 1
	for s in strs:
		if dicts[s] == 1:
			rlt = s
			break
	if rlt == '':
		raise Exception("没有符合条件的值!")
	print("第一个只出现一次的字符: %s" %rlt)
	return rlt

#测试数据
firstCharNotRepeat("abcabefc")
题目二:字符流中第一个只出现一次的字符。(答案:略)

请实现一个函数,用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是’g’;当从该字符流中读出前6个字符"google"时,第一个只出现一次的字符是’l’。

面试题51:数组中的逆序对

题目:在数组中的两个数字,如果前面一个数字大于后面的数字。则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。例如,在数组{7,5,6,4}中,一共存在5个逆序对,分别是(7,6)、(7,5)、(7,4)、(6,4)和(5,4)。

#解答
def numOfReversePair(arr):
    if arr == None or len(arr) <= 1:
        return 0
    count = fuzhuReversePair(arr, 0, len(arr) - 1)
    print("逆序对个数: %s" %count)
    return count

#辅助
def fuzhuReversePair(arr, first, last):
    if first >= last:
        return 0
    mid = (first + last) >> 1
    left = fuzhuReversePair(arr, first, mid)
    right = fuzhuReversePair(arr, mid + 1, last)
    count = merge(arr, first, mid, last)
    return count + left + right

#辅助辅助
def merge(arr, first, mid, last):
    if first >= last:
        return 0
    tmparr = [0 for i in range(last - first + 1)]
    p = mid
    q = last
    idx = last - first
    count = 0
    while p >= first and q >= mid + 1:
        if arr[p] > arr[q]:
            count += (q - mid)
            tmparr[idx] = arr[p]
            p -= 1
            idx -= 1
        else:
            tmparr[idx] = arr[q]
            q -= 1
            idx -= 1
    while p >= first:
        tmparr[idx] = arr[p]
        p -= 1
        idx -= 1
    while q > mid:
        tmparr[idx] = arr[q]
        q -= 1
        idx -= 1
    for a in tmparr:
        arr[first] = a
        first += 1
    return count

#测试数据
arr = [7,5,6,4]
numOfReversePair(arr)
print(arr)

面试题52:两个链表的第一个公共节点

题目:输入两个链表,找出它们的第一个公共节点。链表节点定义如下:
struct ListNode
{
int m_nKey;
ListNode* m_pNext;
};

#定义链表节点
class ListNode():
	def __init__(self, value, next = None):
		self.value = value
		self.next = next

def findFirstCommonNode(head1, head2):
	if head1 == None or head2 == None:
		return None
	lens1 = 0
	lens2 = 0
	newHead1 = head1
	newHead2 = head2
	while newHead1 != None or newHead2 != None:
		if newHead1 != None:
			lens1 += 1
			newHead1 = newHead1.next
		if newHead2 != None:
			lens2 += 1
			newHead2 = newHead2.next
	diff = lens1 - lens2
	newHead1 = head1
	newHead2 = head2
	if diff > 0:
		while diff > 0:
			newHead1 = newHead1.next
			diff -= 1
	elif diff < 0:
		while diff < 0:
			newHead2 = newHead2.next
			diff += 1
	while newHead1 != newHead2 and newHead1 != None and newHead2 != None:
		newHead1 = newHead1.next
		newHead2 = newHead2.next
	if newHead1 == None or newHead2 == None:
		return None
	print(newHead1.value)
	return newHead1

#测试数据
head1 = ListNode(1)
head1_1 = ListNode(0)
head1_2 = ListNode(2)
head2 = ListNode(3)
mid1 = ListNode(5)
mid2 = ListNode(8)
tail = ListNode(9)
head1.next = head1_1
head1_1.next = head1_2
head1_2.next = mid1
mid1.next = mid2
mid2.next = tail
head2.next = mid1
findFirstCommonNode(head1, head2)

面试题53:在排序数组中查找数字

题目一:数字在排序数组中出现的次数。

统计一个数字在排序数组中出现的次数。例如,输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4。

def timesOfNumberKInSortedArray(arr, target):
    if arr == None or len(arr) <= 0:
        raise Exception("输入的参数不合法!")
    if target < arr[0] or target > arr[len(arr) - 1]:
        print("%s 总共出现的次数: 0" %target)
        return 0
    def getFirstK(arr, k):
        if arr == None or len(arr) <= 0:
            raise Exception("输入参数不合法!")
        start = 0
        end = len(arr) - 1
        mid = (start + end) >> 1
        while start < end:
            mid = (start + end) >> 1
            if arr[mid] == k:
                if mid == 0 or arr[mid - 1] != k:
                    return mid
                else:
                    end = mid
            elif arr[mid] < k:
                start = mid + 1
            else:
                end = mid - 1
        return mid

    def getLastK(arr, k):
        if arr == None or len(arr) <= 0:
            raise Exception("输入参数不合法!")
        start = 0
        end = len(arr) - 1
        mid = (start + end) >> 1
        while start < end:
            mid = (start + end) >> 1
            if arr[mid] == k:
                if mid == len(arr) - 1 or arr[mid + 1] != k:
                    print(mid)
                    return mid
                else:
                    start = mid
            elif arr[mid] < k:
                start = mid + 1
            else:
                end = mid - 1
        return mid
    left = getFirstK(arr, target)
    right = getLastK(arr, target)
    print("%s 总共出现的次数: %s" %(target, right - left + 1))
    return right - left + 1
    
#测试数据
timesOfNumberKInSortedArray([1,2,3,3,3,3,4,5], 3)
题目二:0~n-1中缺失的数字。

一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0n-1之内。在范围0n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

def findLostNumber(arr):
	left = 0
	right = len(arr) - 1
	mid = (left + right) >> 1
	while right >= 0 and left < len(arr) and left <= right:
		mid = (left + right) >> 1	
		if arr[mid] == mid:
			left = mid + 1
		elif arr[mid] > mid:
			right = mid - 1
	print("缺失的数字: %s" %left)
	return left

#测试数据
findLostNumber([0,1,2,4])
题目三:数组中数值和下标相等的元素

假设一个单调递增的数组里的每个元素都是整数并且是唯一的。请编程实现一个函数,找出数组中任意一个数值等于其下标的元素。例如,在数组{-3,-1,1,3,5}中,数字3和它的下标相等。

def findNumberEqualIdx(arr):
    left = 0
    right = len(arr) - 1
    mid = (left + right) >> 1
    while right >= 0 and left < len(arr) and left <= right:
        mid = (left + right) >> 1
        if arr[mid] == mid:
            print("符合的数字即索引: %s" %mid)
            return mid
        elif arr[mid] > mid:
            right = mid - 1
        else:
            left = mid + 1
    if arr[mid] == mid:
        print("符合的数字即索引: %s" %mid)
        return mid
    else:
        raise Exception("No suitable element!")

#测试数据
findNumberEqualIdx([-3,-1,1,2,4])

面试题54:二叉搜索树的第k大节点

题目:给定一棵二叉搜索树,请找出其中第k大的节点。例如,在下图54-1中的二叉搜索树里,按节点数值大小顺序,第三大节点的值是4。

图54-1
     5
   /   \
  3     7
 / \   / \
2   4 6   8
#定义二叉树节点
class BinaryTreeNode():
	def __init__(self, value, left = None, right = None):
		self.value = value
		self.left = left
		self.right = right
		
def findKthNumber(root, k):
	arr = []
	def findKthNumberFuZhu(root, arr):
		if root.left != None:
			findKthNumberFuZhu(root.left, arr)
		arr.append(root.value)
		if root.right != None:
			findKthNumberFuZhu(root.right, arr)	
		return arr	
	arr = findKthNumberFuZhu(root, arr)
	if k > len(arr):
		raise Exception("超出范围啦!")
	print(arr[k - 1])
	return arr[k - 1]	

#测试数据
root = BinaryTreeNode(5)
left = BinaryTreeNode(3, BinaryTreeNode(2), BinaryTreeNode(4))
right = BinaryTreeNode(7, BinaryTreeNode(6), BinaryTreeNode(8))
root.left = left
root.right = right
findKthNumber(root, 7)

面试题55:二叉树的深度

题目一:二叉树的深度

输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。

#定义二叉树节点
class BinaryTreeNode():
	def __init__(self, value, left = None, right = None):
		self.value = value
		self.left = left
		self.right = right
				
def depthOfTree(root):
	if root == None:
		return 0
	depth = 1 + max(depthOfTree(root.left), depthOfTree(root.right))
	return depth

#测试数据
root = BinaryTreeNode(5)
left = BinaryTreeNode(3, BinaryTreeNode(2), BinaryTreeNode(4, BinaryTreeNode(5)))
right = BinaryTreeNode(7, BinaryTreeNode(6), BinaryTreeNode(9, BinaryTreeNode(8, BinaryTreeNode(10))))
root.left = left
root.right = right
depth = depthOfTree(root)
print(depth)
题目二:平衡二叉树

输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左、右子树的深度相差不超过1,那么它就是一棵平衡二叉树。例如,图55-2中的二叉树就是一棵平衡二叉树。

图55-2
     1
    / \
   2   3
  / \   \
 4   5   6
    /
   7
#二叉树节点定义
class BinaryTreeNode():
	def __init__(self, value, left = None, right = None):
		self.value = value
		self.left = left
		self.right = right
#从上往下遍历,重复遍历		
def isBalanceTree(root):
	if root == None:
		return True
	def depthOfTree(root):
		if root == None:
			return 0
		depth = 1 + max(depthOfTree(root.left), depthOfTree(root.right))
		return depth
	left = 1 + depthOfTree(root.left)
	right = 1 + depthOfTree(root.right)
	print("abs: %s" %abs(left - right))
	if abs(left - right) > 1:
		return False
	return isBalanceTree(root.left) and isBalanceTree(root.right)

#从下往上遍历
def isBalanceTree2(root):
	if root == None:
		return True
	def isBalanceTreeFuzhu(root):
		if root == None:
			return 1
		left = isBalanceTreeFuzhu(root.left)
		right = isBalanceTreeFuzhu(root.right)
		if abs(left - right) > 1:
			return 0
		return max(left, right) + 1
	balance = isBalanceTreeFuzhu(root)
	return False if balance == 0 else True

#测试数据
root = BinaryTreeNode(1)
left = BinaryTreeNode(2, BinaryTreeNode(4), BinaryTreeNode(5, BinaryTreeNode(7)))
right = BinaryTreeNode(3, None, BinaryTreeNode(6))
root.left = left
root.right = right
print(isBalanceTree(root))
print(isBalanceTree2(root))

面试题56:数组中数字出现的次数

题目一:数组中只出现一次的两个数字

一个整型数组里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
例如,输入数组{2,4,3,6,3,2,5,5},因为只有4和6这两个数字只出现了一次,其他数字都出现了两次,所以输出4和6。

def findTwoUniqueDigits(arr):
  if arr == None or len(arr) <=3:
      raise Exception("输入的数组不符合要求!")
  tmp = 0
  for a in arr:
      tmp ^= a
  x = 1
  while tmp & x == 0:
      x = x << 1
  rlt1, rlt2 = 0, 0
  for a in arr:
      if a & x:
          rlt1 ^= a
      else:
          rlt2 ^= a
  print("rlt1: %s, rlt2: %s." %(rlt1, rlt2))
  return [rlt1, rlt2]

#测试数据
findTwoUniqueDigits([2,4,3,6,3,2,5,5])
题目二:数组中唯一只出现一次的数字

在一个数组中除一个数字只出现一次之外,其他数字都出现了三次,请找出那个只出现一次的数字。

def findUniqueDigitsOtherThree(arr):
  bits = [0 for i in range(32)]
  for a in arr:
      x = 1
      for j in range(31, 0, -1):
          if a & x:
              bits[j] += 1
          x = x << 1
  rlt = 0
  for i in range(32):
      rlt = rlt << 1
      rlt += bits[i] % 3
  print(rlt)
  return rlt

#测试数据
findUniqueDigitsOtherThree([3,3,3,4,4,4,5,5,5,6])

面试题57:和为s的数字

题目一:和为s的两个数字

输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。

def sumEqualS(arr, s):
	if arr == None or len(arr) <= 1:
		raise Exception("输入的数组不符合要求!")
	left = 0
	right = len(arr) - 1
	while left < right:
		if arr[left] + arr[right] < s:
			left += 1
		elif arr[left] + arr[right] > s:
			right -= 1
		else:
			break
	print(arr[left], arr[right])
	return [arr[left], arr[right]]

#测试数据
sumEqualS([1,3,5,6,7,8,10,12,25], 18)
题目二:和为s的连续正数序列

输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。例如,输入15,由于1+2+3+4=4+5+6=7+8=15,所以打印出3个连续序列1~5、4~6和7~8。

def serialSumEqualS(s):
    end = (s >> 1) + 1
    sum = 0
    arr = []
    for i in range(1, end + 1):
        sum += i
        arr.append('%s' %i)
        if sum < s:
            continue
        elif sum > s:
            while sum > s and len(arr) >= 2:
                sum -= int(arr[0])
                arr.pop(0)
            if sum == s:
                print(', '.join(arr))
                sum -= int(arr[0])
                arr.pop(0)           
        else:
            print(', '.join(arr))
            sum -= int(arr[0])
            arr.pop(0)

#测试数据
serialSumEqualS(15)

面试题58:翻转字符串

题目一:翻转单词顺序

输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如,输入字符串"I am a student.“,则输出"student. a am I”。

#python中字符串无法改变(即无法调整字符串内字符的顺序),故需要先把字符串转换为字符列表,再进行旋转操作。
def flipWordOrder(chars):
	def flipWordOrderFuzhu(chars, start, end):
		while start < end:
			tmp = chars[start]
			chars[start] = chars[end]
			chars[end] = tmp
			start += 1
			end -= 1
	flipWordOrderFuzhu(chars, 0, len(chars) - 1)
	start = 0
	for i in range(len(chars)):
		if chars[i] == ' ':
			flipWordOrderFuzhu(chars, start, i - 1)
			start = i + 1
		elif i == len(chars) - 1:
			flipWordOrderFuzhu(chars, start, i)
	return

#测试数据
strs ='abcde e fg.'
print(strs)
chars = list(strs)
flipWordOrder(chars)
print(''.join(chars))
题目二:左旋转字符串

字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。

def turnLeftStrs(chars, num):
	if len(chars) <= 0 or chars == None or num > len(chars):
		raise Exception('输入参数不符合!')
	lens = len(chars)
	def flipWordOrderFuzhu(chars, start, end):
		while start < end:
			tmp = chars[start]
			chars[start] = chars[end]
			chars[end] = tmp
			start += 1
			end -= 1
	flipWordOrderFuzhu(chars, 0, lens - 1)
	flipWordOrderFuzhu(chars, 0, lens - num - 1)
	flipWordOrderFuzhu(chars, lens - num, lens - 1)
	print(''.join(chars))
	return 

#测试数据
strs = 'abcdefg'
turnLeftStrs(list(strs), 3)

面试题59:队列的最大值

题目一:滑动窗口的最大值

给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,它们的最大值分别为{4,4,6,6,6,5},如表59-1所示。

表59-1
——————————————————————————————————————
| 数组中的滑动窗口  | 滑动窗口中的最大值|
——————————————————————————————————————
|[2,3,4],2,6,2,5,1|        4         |
|2,[3,4,2],6,2,5,1|        4         |
|2,3,[4,2,6],2,5,1|        6         |
|2,3,4,[2,6,2],5,1|        6         |
|2,3,4,2,[6,2,5],1|        6         |
|2,3,4,2,6,[2,5,1]|        5         |
——————————————————————————————————————
#时间复杂度稍高
def maxVofQueue(arr, size):
    import numpy as np
    if arr == None or len(arr) <= 0 or len(arr) < size:
        raise Exception("输入参数不符合!")
    idx = 0
    maxV = -np.inf
    maxArr = []
    for i in range(size):
        if arr[i] >= maxV:
            maxV = arr[i]
            idx = i
    maxArr.append(maxV)
    for i in range(size, len(arr)):
        if i - idx + 1 > size:
            idx += 1
            maxV = arr[idx]
            for j in range(idx, i + 1):
                if arr[j] >= maxV:
                    maxV = arr[j]
                    idx = j
        else:
            if arr[i] >= maxV:
                maxV = arr[i]
                idx = i
        maxArr.append(maxV) 
    print(maxArr)
    return maxArr

#测试数据
maxVofQueue([2,3,4,2,6,2,5,1,6], 2)

#维护索引列表,空间复杂度稍高
def maxVofQueue2(arr, size):
    if arr == None or len(arr) <= 0 or len(arr) < size:
        raise Exception("输入参数不符合!")
    idxDeque = []
    maxArr = []
    for i in range(size):
        while idxDeque and arr[i] >= arr[idxDeque[-1]]:
            idxDeque.pop()
        idxDeque.append(i)
    maxArr.append(arr[idxDeque[0]])
    for i in range(size, len(arr)):
        while idxDeque and arr[i] >= arr[idxDeque[-1]]:
            idxDeque.pop()  
        if idxDeque and idxDeque[0] < i - size + 1:
            idxDeque.pop(0)
        idxDeque.append(i)
        maxArr.append(arr[idxDeque[0]])
    print(maxArr)
    return maxArr

#测试数据
maxVofQueue2([2,3,4,2,6,2,5,1,6], 2)

题目二:队列的最大值
请定义一个队列,并实现函数max得到队列里的最大值,要求函数max、push_back和pop_front的时间复杂度都是O(1)。

class MaxValueOfQueue():
	def __init__(self, idx = 0, deque1 = [], deque2 = []):
		self.deque1 = deque1
		self.deque2 = deque2
		self.idx = idx
	class QueueData():
		def __init__(self, idx = None, value = None):
			self.idx = idx
			self.value = value
	def push_back(self, e):
		import sys
		while self.deque2 and e >= self.deque2[-1].value:
			self.deque2.pop()
		queueData = self.QueueData(self.idx, e)
		self.deque1.append(queueData)
		self.deque2.append(queueData)
		self.idx += 1
		if self.idx == sys.maxsize:
			self.idx = 0
	def pop_first(self):
		if not self.deque1:
			raise Exception("队列中没有数据啦!")
		if self.deque1[0].idx == self.deque2[0].idx:
			self.deque2.pop(0)
		return self.deque1.pop(0).value
	def max(self):
		if not self.deque2:
			raise Exception("队列中没有数据啦!")
		return self.deque2[0].value

#测试数据
que = MaxValueOfQueue()
que.push_back(6)
que.push_back(4)
que.push_back(5)
que.push_back(3)
que.push_back(0)
que.push_back(-1)

print(que.max())
que.pop_first()
print(que.max())
que.pop_first()
print(que.max())
que.pop_first()
print(que.max())
que.pop_first()
print(que.max())

面试题60:n个骰子的点数

把n个骰子扔在地上,所有骰子朝上一面的点数和为s。输入n,打印出s的所有可能的值出现的概率。

#循环法
def probabilityLoop(n):
	def getNSumLoop(n, arr):
		if n < 1 or len(arr) < 6 * n - n + 1:
			return
		arr[0] = arr[1] = arr[2] = arr[3] = arr[4] = arr[5] = 1
		if n == 1:
			return
		#骰子的个数
		for i in range(2, n + 1):
			for sum in range(6 * i, i - 1, -1):
				tmp1 = arr[(sum - (i - 1)) - 1] if (sum - (i - 1)) - 1 >= 0 else 0
				tmp2 = arr[(sum - (i - 1)) - 2] if (sum - (i - 1)) - 2 >= 0 else 0
				tmp3 = arr[(sum - (i - 1)) - 3] if (sum - (i - 1)) - 3 >= 0 else 0
				tmp4 = arr[(sum - (i - 1)) - 4] if (sum - (i - 1)) - 4 >= 0 else 0
				tmp5 = arr[(sum - (i - 1)) - 5] if (sum - (i - 1)) - 5 >= 0 else 0
				tmp6 = arr[(sum - (i - 1)) - 6] if (sum - (i - 1)) - 6 >= 0 else 0
				arr[sum - i] = tmp1 + tmp2 + tmp3 + tmp4 + tmp5 + tmp6
		return
	arr = [0 for i in range(n, 6 * n + 1)]
	getNSumLoop(n, arr)
	for a in arr:
		print('%.2f%% ' %(a * 1.0 / sum(arr) * 100), end = ' ')
	print()

#测试数据
probabilityLoop(2)

#动态规划
#动态规划公式(n >=2 时)
# F(n, sum) = F(n-1, sum - 1) + F(n-1, sum - 2) + F(n-1, sum - 3) + F(n-1, sum - 4) + F(n-1, sum - 5) + F(n-1, sum - 6)
def probabilityDynamic(n):
	def dynamic(n, sum):
		if n < 1 or sum < n or sum > 6 * n:
			return 0
		if n == 1 and sum >= 1 and sum <= 6:
			return 1
		return dynamic(n - 1, sum - 1) + dynamic(n - 1, sum - 2) + dynamic(n - 1, sum - 3) + dynamic(n - 1, sum - 4) + dynamic(n - 1, sum - 5) + dynamic(n - 1, sum - 6)
	arr = [0 for i in range(n, 6 * n + 1)]
	for i in range(n, 6 * n + 1):
		arr[i - n] = dynamic(n, i)
	total = sum(arr)
	for a in arr:
		print("%.2f%% " %(a *1.0 / total * 100), end = ' ')
	print()

#测试数据
probabilityDynamic(2)

面试题61:扑克牌中的顺子

题目:从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大小王可以看成任意数字。

def shunziInPlayingCard(arr):
	def quickSort(arr, start, end):
		if end <= start or arr == None or len(arr) <= 1:
			return 
		first = start
		last = end
		a = arr[first]
		while start < end:
			if arr[end] >= a:
				end -= 1
			elif arr[start] <= a:
				start += 1
			else:
				tmp = arr[start]
				arr[start] = arr[end]
				arr[end] = tmp
		# if start > first:
		arr[first] = arr[start]
		arr[start] = a
		quickSort(arr, first, start - 1)
		quickSort(arr, start + 1, last)
		return
	quickSort(arr, 0, len(arr) - 1)
	numZero = 0
	diff = 0
	for i in range(0, len(arr) - 1):
		if arr[i] == 0:
			numZero += 1
		else:
			diff += arr[i + 1] - arr[i] - 1
	print(numZero)
	print(diff)
	if diff <= numZero:
		return True
	else:
		return False

#测试数据
print(shunziInPlayingCard([0,0,3,4,6]))

面试题62:圆圈中最后剩下的数字

题目:0,1,···,n-1这个n个数字排成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字。求出这个圆圈里剩下的最后一个数字。
例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。

def theRemainingNumber(m, n):
    a = []
    tmp = n
    for i in range(m):
        tmp -= 1  
        if tmp != 0:
            a.append(i)
        else:
            tmp = n
            continue
    while len(a) > 1:
    	tmp -= 1
    	if tmp != 0:
    		a.append(a.pop(0))
    	else:
    		tmp = n
    		a.pop(0)
    print(a[0])		
    return a[0]		

#测试数据
theRemainingNumber(5, 3)

面试题63:股票的最大利润

题目: 假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?例如,一只股票在某些时间节点的价格为{9,11,8,5,7,12,16,14}。如果我们能够在价格为5的时候买入并在价格为16时卖出,则能收获最大的利润11。

def maxProfitOfStock(arr):
	import numpy as np
	arr_o = [arr[i] - arr[i - 1] for i in range(1, len(arr))]
	max_v = -np.inf
	acc = 0
	for a in arr_o:
		acc = max(acc + a, a)
		max_v = max(acc, max_v)
	print(max_v)
	return max_v

#测试数据
maxProfitOfStock([9,11,8,5,7,12,16,14])

面试题64:求 1+2+···+n

题目:求1+2+···+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

def sumSolution1(n):
	sum = pow(n, 2) + n
	print(sum >> 1)
	return sum >> 1

#测试数据
sumSolution1(5)

def sumSolution2(n):
	return n and (n + sumSolution2(n - 1))

#测试数据
print(sumSolution2(5))

面试题65:不用加减乘除做加法

题目:写一个函数,求两个整数之和,要求在函数体内不得使用"+“、”-"、“×”、"÷"四则运算符号。

def getSumWithBitOperation(a, b):
	sums = a ^ b
	while a & b:
		a = (a & b) << 1
		b = sums 
		sums = a ^ b
	print(sums)
	return sums

#测试数据
getSumWithBitOperation(20,301)

面试题66:构建乘积数组

题目:给定一个数组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]。不能使用除法。

def buildProductArray(A):
	n = len(A)
	B = [0 for i in range(n)]
	C = [0 for i in range(n)]
	D = [0 for i in range(n)]
	C[0] = A[0]
	D[0] = A[n - 1]
	for i in range(1, n):
		C[i] = C[i - 1] * A[i]
		D[i] = D[i - 1] * A[(n - 1) - i]

	for i in range(n):
		if i == 0:
			B[i] = D[(n - 1) - (i + 1)]
		elif i == n - 1:
			B[i] = C[i - 1]
		else:
			B[i] = C[i - 1] * D[(n - 1) - (i + 1)]
	print(B)
	return B

#测试数据
a = [1, 2, 3, 4]
buildProductArray(a)

面试题67:字符串转换成整数

题目:把字符串转换成整数

def changeStrToInt(strs):
	sign = False
	flag = True
	if strs == None or len(strs) <= 0:
		raise Exception("输入的字符串为空或者没有输入任何参数!")
	if strs[0] == '0':
		for i in range(1, len(strs)):
			if strs[i] != '0':
				raise Exception("以0开头,但是中间出现了不为0的字符!")
		print(0)
		return 0
	elif strs[0] == '+' or strs[0] == '-':
		if len(strs) <= 1:
			raise Exception("只有正负号,没有数字,不合法!")
		sign = True
		if strs[0] == '-':
			flag = False
		for i in range(1, len(strs)):
			if strs[i] > '9' or strs[i] < '0':
				raise Exception("输入的字符串中含有不能转化为整数的字符!")		
	else:
		for i in range(len(strs)):
			if strs[i] > '9' or strs[i] < '0':
				raise Exception("输入的字符串中含有不能转化为整数的字符!")
	rlt = 0
	if sign:
		for i in range(1, len(strs)):
			rlt = rlt * 10 + ord(strs[i]) - ord('0')
	else:
		for i in range(len(strs)):
			rlt = rlt * 10 + ord(strs[i]) - ord('0')		
	print(rlt if flag else -rlt)
	return rlt if flag else -rlt

#测试数据
changeStrToInt('-456')

面试题68:树中两个节点的最低公共祖先

题目一:求一棵二叉搜索树的两个节点的最低公共祖先,其中二叉搜索树中每个节点的值都不相同。
#二叉树节点定义
class BinaryTreeNode():
	def __init__(self, value, left = None, right = None):
		self.value = value
		self.left = left
		self.right = right

#适用于二叉搜索树
def findLowestPNode(root, child1, child2):
	if root == None or child1 == None or child2 == None:
		return None
	if child1.value > child2.value:
		tmp = child1
		child1 = child2
		child2 = tmp
	res = None
	if root.value > child1.value and root.value < child2.value:
		res = root
	if root.value > child1.value and root.value > child2.value:
		res = findLowestPNode(root.left, child1, child2)
	if root.value < child1.value and root.value < child2.value:
		res = findLowestPNode(root.right, child1, child2)
	if res !=None:
		print(res.value)
	return res;

#测试数据
root = BinaryTreeNode(8, BinaryTreeNode(6, BinaryTreeNode(5), BinaryTreeNode(7)), BinaryTreeNode(10, BinaryTreeNode(9), BinaryTreeNode(11)))
child1 = BinaryTreeNode(5)
child2 = BinaryTreeNode(7)

findLowestPNode(root, child1, child2)
题目二:求一棵普通二叉树的两个节点的最低公共祖先。
#二叉树节点定义
class BinaryTreeNode():
	def __init__(self, value, left = None, right = None):
		self.value = value
		self.left = left
		self.right = right
		
#普通二叉树(没有父指针)
def findLowestPNodeOrdinary(root, child1, child2):
	pathOne = []
	pathTwo = []
	pathOne.append(root)
	pathTwo.append(root)
	def findPath(root, child, path):
		if root == child:
			return True
		if root.left != None:
			path.append(root.left)
			if findPath(root.left, child, path):
				return True
			path.pop()
		if root.right != None:
			path.append(root.right)
			if findPath(root.right, child, path):
				return True
			path.pop()
		return False
	findPath(root, child1, pathOne)
	findPath(root, child2, pathTwo)
	print(len(pathOne))
	print(len(pathTwo))
	res = None
	for i in range(min(len(pathOne), len(pathTwo)) - 1):
		if pathOne[i + 1] != pathTwo[i + 1]:
			res = pathOne[i]
			break
	return res

#递归-普通二叉树(没有父指针)
def findLowestPNodeOrdinaryRecursive(root, child1, child2):
	if root == None or root == child1 or root == child2:
		return root
	left = findLowestPNodeOrdinaryRecursive(root.left, child1, child2)
	right = findLowestPNodeOrdinaryRecursive(root.right, child1, child2)
	if left == None:
		return right
	if right == None:
		return left
	return root

#测试数据
root = BinaryTreeNode(8)
left_1_1 = BinaryTreeNode(6)
left_2_1 = BinaryTreeNode(5)
left_2_2 = BinaryTreeNode(9)	
right_1_1 = BinaryTreeNode(10)
right_2_1 = BinaryTreeNode(7)
right_2_2 = BinaryTreeNode(11)

root.left = left_1_1
root.right = right_1_1
left_1_1.left = left_2_1
left_1_1.right = right_2_1
right_1_1.left = left_2_2
right_1_1.right = right_2_2

child1 = left_2_1
child2 = right_2_1

res = findLowestPNodeOrdinary(root, child1, child2)
if res != None:
	print(res.value)

res = findLowestPNodeOrdinaryRecursive(root, child1, child2)
if res != None:
	print(res.value)

如有问题,欢迎批评指正,谢谢!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值