因为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)
# -*- coding:utf-8 -*-
class Solution:
def jumpFloorII(self, number):
# write code here
if number == 0:
return 0
if number ==1:
return 1
else:
return 2 * self.jumpFloorII(number - 1)
或者直接套用数学归纳出来的公式 2 **(n-1)
# -*- coding:utf-8 -*-
class Solution:
def jumpFloorII(self, number):
# write code here
if number == 0:
return 0
else:
return 2 **(number - 1)
面试题11:旋转数组的最小数字_牛客题霸_牛客网
python代码没办法全部通过,需要再看看java
面试题15:二进制中1的个数
对于负数,最高位为1,而负数在计算机是以补码存在的,往右移,符号位不变,符号位1往右移,最终可能会出现全1的情况,导致死循环。与0xffffffff相与,就可以消除负数的影响
# -*- coding:utf-8 -*-
class Solution:
def NumberOf1(self, n):
# write code here
if n < 0: # python没有无符号移动,负数需要处理下
n = n & 0xffffffff
return bin(n).count('1')
面试题16:数值的整数次方
# -*- coding:utf-8 -*-
class Solution:
def Power(self, base, exponent):
# write code here
flag = 0 # 判断是否为负数的标志
if base == 0 and exponent == 0:
return 'Input error'
elif base == 0:
return 0
elif exponent == 0:
return 1
elif exponent < 0:
flag = 1 # 如果幂为负数,则将标志置为1
exponent = -exponent
i = 1
result = 1
while i <= exponent:
result *= base
i += 1
if flag == 1:
return 1/result
else:
return result
面试题20:表示数值的字符串
# -*- coding:utf-8 -*-
class Solution:
# s字符串
def isNumeric(self, s):
if not s:
return
sign, point, hasE = False, False, False
for i in range(len(s)):
if s[i].lower() == 'e': # 判断e的存在及个数
if hasE: # 有两个e
return False
if i == len(s)-1: # e位于字符串最后
return False
hasE = True
elif s[i] == '+' or s[i] == '-':
if sign and s[i-1].lower() != 'e': # + -第二次出现 但并未位于e之后
return False
# 如果 + - 第一次出现且出现于字符串中间但并位于e之后
if not sign and i > 0 and s[i-1].lower() != 'e':
return False
sign = True
elif s[i] == '.': # 两个小数点或小数点与e不能同时出现
if hasE or point:
return False
point = True
elif ord(s[i]) < ord('0') or ord(s[i]) > ord('9'): # 如果当前字符不是一个数字
return False
return True
面试题21:调整数组顺序使奇数位于偶数前面
# -*- coding:utf-8 -*-
class Solution:
def reOrderArray(self, array):
arr1 = []
arr2 = []
for num in array:
if num % 2 == 1:
arr1.append(num)
else:
arr2.append(num)
arr1.extend(arr2)
return arr1
面试题29:顺时针打印矩阵
# -*- coding:utf-8 -*-
class Solution:
# matrix类型为二维列表,需要返回列表
def printMatrix(self, matrix):
res = []
while matrix: # 只要矩阵不为空就一直循环
res += matrix.pop(0) # 方向:上
if matrix and matrix[0]: # 方向:右 第二个条件 确保是一个二维数组
for row in matrix:
res.append(row.pop())
if matrix: # 方向:下
res += matrix.pop()[::-1]
if matrix and matrix[0]: # 方向:左
for row in matrix[::-1]:
res.append(row.pop(0))
return res
面试题31:栈的压入、弹出序列
# -*- coding:utf-8 -*-
class Solution:
def IsPopOrder(self, pushV, popV):
stack = []
pushLen = len(pushV)
popLen = len(popV)
if pushLen != popLen:
return False
pushIndex = 0
popIndex = 0
while pushIndex < pushLen:
stack.append(pushV[pushIndex])
pushIndex += 1
while len(stack) != 0 and stack[-1] == popV[popIndex]:
stack.pop()
popIndex += 1
return len(stack) == 0 and pushIndex == popIndex
面试题33:二叉搜索树的后序遍历序列
# -*- coding:utf-8 -*-
class Solution:
def VerifySquenceOfBST(self, sequence):
if len(sequence) == 0:
return False
root = sequence[-1] # 最后一个为根节点
n = len(sequence)-1 # 最后一个元素的索引
i = 0
while i < n: # 找到第一个大于跟结点的位置
if sequence[i] > root:
break
i += 1
j = i
while j < n: # 判断右子树的元素是否都比根节点大
if sequence[j] < root:
return False
j += 1
left = True
right = True
if i != 0: # 避免 i = 0
left = self.VerifySquenceOfBST(sequence[:i])
right = self.VerifySquenceOfBST(sequence[i:])
return left and right
面试题34:二叉树中和为某一值的路径
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回二维列表,内部每个列表表示找到的路径
def __init__(self):
self.sums = 0 # 存放当前和
self.rode = [] # 当前路径
self.res = [] # 二维结果列表
def FindPath(self, root, expectNumber):
if not root or not expectNumber:
return []
self.sums += root.val
self.rode.append(root.val)
if not root.left and not root.right and self.sums == expectNumber:
# 注意此处是self.rode[:] 不加[:] 直接使用变量名会返回空的二维列表
# 可变对象与不可变对象的复制 隐藏很深的bug!!
self.res.append(self.rode[:]) # 这里也不能直接return 因为后边还要逐个弹出
self.FindPath(root.left, expectNumber)
self.FindPath(root.right, expectNumber)
self.sums -= root.val
self.rode.pop()
return self.res
面试题35:复杂链表的复制
# -*- coding:utf-8 -*-
# class RandomListNode:
# def __init__(self, x):
# self.label = x
# self.next = None
# self.random = None
class Solution:
# 返回 RandomListNode
def Clone(self, pHead):
if not pHead:
return None
# 第一步:复制节点在原节点之后
pCur = pHead
while pCur:
node = RandomListNode(pCur.label)
node.next = pCur.next
pCur.next = node
pCur = node.next
# 第二步:复制random节点
pCur = pHead
while pCur:
if pCur.random:
pCur.next.random = pCur.random.next
pCur = pCur.next.next
# 第三步:将新旧链表分离
pCur = pHead
head = pHead.next
cur = head
while pCur:
pCur.next = pCur.next.next
if cur.next:
cur.next = cur.next.next
cur = cur.next
pCur = pCur.next
return head
面试题36:二叉搜索树与双向链表
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def __init__(self):
self.head = None
self.end = None
def Convert(self, root):
if not root:
return
self.Convert(root.left)
root.left = self.end
if self.end:
self.end.right = root
else:
self.head = root
self.end = root
self.Convert(root.right)
return self.head
面试题37:序列化二叉树
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def Serialize(self, root):
def pre_order(root):
if not root:
result.append('#')
return
result.append(str(root.val))
pre_order(root.left)
pre_order(root.right)
result = []
pre_order(root)
return ' '.join(result)
def Deserialize(self, s):
vals = iter(s.split())
def pre_order():
val = next(vals)
if val == '#':
return None
root = TreeNode(int(val))
root.left = pre_order()
root.right = pre_order()
return root
return pre_order()
面试题38:字符串的排列
# -*- coding:utf-8 -*-
class Solution:
def Permutation(self, ss):
if not ss: # 递归出口
return []
n = len(ss)
if n == 1:
return [ss]
res = []
for i in range(n): # 逐渐缩小问题的规模
tmp = self.Permutation(ss[:i]+ss[i+1:]) # 对除当前字符外的其他字符进行全排列
for j in tmp:
res.append(ss[i]+j) # 将该字符与全排列的其余字符做拼接
return sorted(list(set(res))) # 对拼接后的字符 去重 排序
面试题39:数组中出现次数超过一半的数字
看书
面试题40:最小的k个数
# -*- coding:utf-8 -*-
################## 八大排序算法实现最小的K个数 #######################
class Solution:
# 选择排序
def select_sort(self, tinput):
n = len(tinput)
for i in range(n):
min_i = i
for j in range(i+1, n):
if tinput[min_i] > tinput[j]:
min_i = j
tinput[i], tinput[min_i] = tinput[min_i], tinput[i]
return tinput
# 冒泡排序(优化版)
def bubble_sort(self, tinput):
n = len(tinput)
for i in range(n)[::-1]:
count = 0
for j in range(i):
if tinput[j] > tinput[j+1]:
tinput[j], tinput[j+1] = tinput[j+1], tinput[j]
count += 1
if count == 0:
return tinput
return tinput
# 插入排序
def insert_sort(self, tinput):
n = len(tinput)
for i in range(1, n):
j = i
while j >0:
if tinput[j] < tinput[j-1]:
tinput[j], tinput[j-1] = tinput[j-1], tinput[j]
j -= 1
else:
break
return tinput
# 希尔排序
def shell(self,tinput):
n = len(tinput)
gap = n // 2 # 使用不同的gap对数组进行预排序
while gap >0:
for i in range(gap, n): # 对每一个gap都需要对gap后的每一个关键字进行插入排序
j = i # 初始化一个指针
while j >= gap:
if tinput[j] < tinput[j - gap]: # 对一个gap进行插入排序
tinput[j], tinput[j - gap] = tinput[j - gap], tinput[j]
j -= gap # 一个gap的前一个关键字
else:
break
gap = gap // 2
return tinput
# 快速排序
def quick_sort(self, tinput,left, right):
if left >= right: # 递归出口
return tinput
i = left
j = right
tmp = tinput[i] # 选当前序列的第一个关键字为枢纽
while i < j: # 完成一次排序 将小于tmp的值放到tmp的左边,大于tmp的值放到tmp的右边
while i < j and tinput[j] >= tmp: # 从右往左扫描,找到一个小于tmp的关键字
j -= 1
tinput[i] = tinput[j]
while i < j and tinput[i] <= tmp: # 从左往右扫描,找到一个大于tmp的关键字
i += 1
tinput[j] = tinput[i]
tinput[i] = tmp # 一次循环结束后,i = j
self.quick_sort(tinput,left, i-1)
self.quick_sort(tinput,i+1, right)
return tinput
# 归并排序
def merge_sort(self,tinput):
def merge(list1, list2):
i, j = 0, 0
n1 = len(list1)
n2 = len(list2)
result = []
while i < n1 and j < n2:
if list1[i] <= list2[j]:
result.append(list1[i])
i += 1
else:
result.append(list2[j])
j += 1
if list1:
result.extend(list1[i:]) # 注意这里是extend而不是append
#result += list1[i:] # 这样写也可以 [] + [] ==> [].entend([])
if list2:
result.extend(list2[j:])
return result
n = len(tinput)
if n <=1:
return tinput
tmp = n/2
left = self.merge_sort(tinput[:tmp])
right = self.merge_sort(tinput[tmp:])
return merge(left, right)
# 堆排序
def heap_sort(self,lists):
def adjust_heap(lists, i, size): # 输入参数:数组,调整节点位置,数组长度
lchild = 2 * i + 1 # 当前结点左孩子的索引
rchild = 2 * i + 2 # 当前结点右孩子的索引
maxs = i
if i < size // 2: # 如果当前结点为非叶子节点
if lchild < size and lists[lchild] > lists[maxs]:
maxs = lchild
if rchild < size and lists[rchild] > lists[maxs]:
maxs = rchild
if maxs != i: # 如果当前结点满足大顶堆要求不交换,不满足进行交换并对其孩子结点进行调整
lists[maxs], lists[i] = lists[i], lists[maxs]
adjust_heap(lists, maxs, size) # 对交换后的孩子结点进行调整
def build_heap(lists, size): # 输入参数为:数组,数组长度
for i in range(size//2)[::-1]: # 对每一个非叶子节点进行调整
adjust_heap(lists, i, size)
size = len(lists)
build_heap(lists, size) # 对当前数组,建一个大顶堆
for i in range(size)[::-1]: # 依次将第i大的元素放到第i个位置
lists[0], lists[i] = lists[i], lists[0]
adjust_heap(lists, 0, i) # 对堆顶位置进行调整
return lists
# 基数排序
def radix(self, tinput):
if not tinput:
return []
k = len(str(max(tinput)))
bucket = [[] for i in range(10)]
for i in range(k):
for num in tinput:
bucket[num/(10**i)%10].append(num)
del tinput[:]
for z in bucket:
tinput += z
del z[:]
return tinput
def GetLeastNumbers_Solution(self, tinput, k):
left = 0
right = len(tinput)-1
#tinput = self.select_sort(tinput)
#tinput = self.insert_sort(tinput)
#tinput = self.bubble_sort(tinput)
#tinput = self.shell(tinput)
#tinput = self.quick_sort(tinput,left,right)
#tinput = self.radix(tinput)
#tinput = self.heap_sort(tinput)
tinput = self.merge_sort(tinput)
n = len(tinput)
if k<=n:
return tinput[:k]
else:
return []
面试题41:数据流中的中位数
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.arr = []
def Insert(self, num):
self.arr.append(num)
def GetMedian(self,x):
self.arr.sort()
n = len(self.arr)
m = n // 2
if n % 2 == 0:
return (self.arr[m] + self.arr[m-1])/2.0
return self.arr[m]
面试题42:连续子数组的最大和
从前往后加,加入新元素后如果和大于零则有用,小于零将 sub_sum置为零则重新开始记录
# -*- coding:utf-8 -*-
class Solution:
def FindGreatestSumOfSubArray(self, array):
max_sum = 0
sub_sum = 0
for num in array:
sub_sum += num
if sub_sum < 0:
sub_sum = 0
if sub_sum > max_sum:
max_sum = sub_sum
if max_sum == 0:
return max(array)
return max_sum
面试题43:1-n整数中1出现的次数
# -*- coding:utf-8 -*-
class Solution:
def NumberOf1Between1AndN_Solution(self, n):
# write code here
a = ''
for i in range(1, n+1):
a += str(i)
return a.count("1")
面试题45:把数组排成最小的数
# -*- coding:utf-8 -*-
# python3的sort方法没有了cmp参数,需要对其key参数进行以下处理
# import functools.cmp_to_key
# key = cmp_to_key(self.cmp)
class Solution:
def cmp(self, a, b):
return 1 if a+b > b+a else -1
def PrintMinNumber(self, numbers):
string = map(str, numbers) # string = [str(num) for num in numbers]
string.sort(self.cmp)
return ''.join(string)
面试题:字符流中第一个不重复的元素
# -*- coding:utf-8 -*-
class Solution:
# 返回对应char
def __init__(self):
self.s = '' # 用于记录加入的总字符串
self.dic = dict() # 用于统计单个字符串出现的次数
def FirstAppearingOnce(self):
for i in self.s:
if self.dic[i] == 0:
return i
return '#'
def Insert(self, char): # 用于添加单个字符
self.s += char
if char not in self.dic:
self.dic[char] = 0
else:
self.dic[char] += 1
面试题49:丑数
# -*- coding:utf-8 -*-
class Solution:
def GetUglyNumber_Solution(self, index):
if index <= 1:
return index
res = [1] * index
i2, i3, i5 = 0, 0, 0 # 声明三个索引,可看做是存放排序丑数分别乘以2 3 5的三个队列
for i in range(1, index):# 循环一次产生一个大于已有序丑数的最小丑数
num2 = res[i2]*2 # 产生最有可能的三个丑数
num3 = res[i3]*3
num5 = res[i5]*5
res[i] = min(num2, min(num3, num5)) # 在产生的三个丑数当中选取最小的一个
if res[i] == num2:
i2 += 1
if res[i] == num3:
i3 += 1
if res[i] == num5:
i5 += 1
return res[-1]
面试题52:两个链表的第一个公共结点
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
if not pHead1 or not pHead2:
return
p, q = pHead1, pHead2
len1, len2 = 0, 0
while p:
len1 += 1
p = p.next
while q:
len2 += 1
q = q.next
if len1 > len2:
p, q = pHead1, pHead2
else:
p, q = pHead2, pHead1
for i in range(abs(len1-len2)):
p = p.next
while p != q:
p = p.next
q = q.next
return p
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
if not pHead1 or not pHead2:
return
dic = dict()
while pHead1: # 将该链表放入字典中(哈希表)查找时间复杂度为O(1)
dic[pHead1] = 0
pHead1 = pHead1.next
while pHead2:
if pHead2 in dic:
return pHead2
pHead2 = pHead2.next
return
面试题55:
题目二 平衡二叉树:
如果直接从上向下计算树的深度,判断是否满足平衡二叉树的定义,会多次重复遍历下层结点,增加了不必要的开销。
如果改为从下往上遍历,如果子树是平衡二叉树,则返回子树的高度;如果发现子树不是平衡二叉树,则直接停止遍历,这样至多只对每个结点访问一次。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def get_depth(self, p):
if not p:
return 0
left = self.get_depth(p.left) # 当前结点左子树的深度
if left == -1: # 左子树不是平衡二叉树
return -1
right = self.get_depth(p.right) # 当前结点右子树的深度
if right == -1: # 右子树不是平衡二叉树
return -1
if abs(left - right) > 1: # 如果以当前结点为根节点的树不是平衡二叉树
return -1
else:
return max(left, right) + 1 # 当前子树为平衡二叉树,返回当前子树的深度
def IsBalanced_Solution(self, p):
return self.get_depth(p) != -1
另一种解法:复杂度较高
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def treeDepth(self, root):
if root == None:
return 0
return max(self.treeDepth(root.left),self.treeDepth(root.right)) + 1
def IsBalanced_Solution(self, pRoot):
if pRoot == None:
return True
return abs(self.treeDepth(pRoot.left) - self.treeDepth(pRoot.right))<= 1
面试题57:和为S的两个数字
# -*- coding:utf-8 -*-
class Solution:
def FindNumbersWithSum(self, array, tsum):
# write code here
min_mul = float('inf') # 将初始最小值设置为无穷大,负无穷:-float('inf') 或 float('-inf'),其中,inf 均可以写成 Inf
min_i = 0
for i in array:
if tsum - i in array and i * (tsum - i) < min_mul:
min_i = i
min_mul = i * (tsum - i)
if min_mul == float('inf'):
return []
a = [min_i, tsum - min_i]
sorted(a)
return a[0], a[1]
# 方法二
# -*- coding:utf-8 -*-
class Solution:
def FindNumbersWithSum(self, array, tsum):
dic = dict()
result = []
min_res = 999999999
min_lst = []
for num in array:
dic[num] = num
for i in array:
if tsum - i in dic:
result.append([i, tsum - i])
for lst in result:
if lst[0]*lst[1] < min_res:
min_res = lst[0]*lst[1]
min_lst = lst
return sorted(min_lst)
题目二:和为S的连续正数序列
# -*- coding:utf-8 -*-
class Solution:
def FindContinuousSequence(self, s):
i, j = 1, 2
res = []
while i < (s+1)//2: # 较小的值增加到该值结束
tmp = sum(range(i,j+1)) # 对i-j之间的序列求和
if tmp < s: # 当前序列和较小 对j加一
j += 1
elif tmp > s: # 当前序列和较大对i加一
i += 1
else: # tmp = s时
res.append(range(i, j+1))
j += 1 # 或者i += 1 制造新的不相等 避免死循环
return res
面试题58:翻转字符串
题目二:左旋转字符串
# -*- coding:utf-8 -*-
class Solution:
def LeftRotateString(self, s, n):
# write code here
return s[n:] + s[:n]
面试题:数组中只出现一次的数字
# -*- coding:utf-8 -*-
class Solution:
# 返回[a,b] 其中ab是出现一次的两个数字
def FindNumsAppearOnce(self, array):
# write code here
sum = 0
for i in array:
sum ^= i
for i in array:
if i^sum in array:
return [i, i^sum]
面试题61:扑克牌中的顺子
# -*- coding:utf-8 -*-
class Solution:
def IsContinuous(self, numbers):
if not numbers:
return False
numbers.sort() # 第一步:先对数组排序
zero_num = numbers.count(0) # 第二步:计算数组中大小王的个数
for i in range(len(numbers)-1):
if numbers[i] != 0:
if numbers[i] == numbers[i+1]: # 出现对子直接返回
return False
zero_num = zero_num - (numbers[i+1] - numbers[i])+1 #第三步:弥补空缺数
if zero_num < 0:
return False
return True
面试题66:构建乘积数组
# -*- coding:utf-8 -*-
class Solution:
def multiply(self, A):
if not A:
return []
n = len(A)
B = [1]*n
for i in range(1, n): # 计算A正三角并将值赋给B的相应位置
B[i] = B[i-1] * A[i-1]
temp = 1 # 倒三角第一个元素初始化为1
for i in range(n-2, -1, -1):
temp *= A[i+1] # 计算倒三角
B[i] *= temp # 得到最终结果
return B
面试题67:把字符串转换成整数
# -*- coding:utf-8 -*-
class Solution:
def StrToInt(self, s):
if not s:
return 0
res = 0
flag = 1
for i in range(len(s)):
if i == 0 and s[i] == '+':
continue
elif i == 0 and s[i] == '-':
flag = -1
continue
n = ord(s[i]) - ord('0') # 计算当前字符所对应数字的ASC码
if n>=0 and n<=9:
res = 10*res + n
else:
return 0
return res * flag