1.用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
class CQueue:
def __init__(self):
self.add_stack, self.pop_stack = [], []
def appendTail(self, value: int) -> None:
self.add_stack.append(value)
def deleteHead(self) -> int:
if self.pop_stack:
return self.pop_stack.pop() # popstack有则退出
else:
if not self.add_stack: # addstack为空返回-1
return -1
while self.add_stack: # addstack需要全部退完,用while
self.pop_stack.append(self.add_stack.pop())
return self.pop_stack.pop()
2.写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下:
F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
class Solution:
def fib(self, n: int) -> int:
a, b = 0, 1
for i in range(n):
a, b = b, a + b
return a % 1000000007
3.找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
dic = set() # 建立一个集合,如果在集合里面,则返回
for num in nums:
if num in dic: return num
dic.add(num)
return -1
4.在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
flag0 = 0
flag1 = 1
for list_ in matrix:
if target in list_:
flag0 = 1
return flag0 == flag1
if flag0 == 0:
return flag0 == flag1
5.请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
输入:s = “We are happy.”
输出:“We%20are%20happy.”
class Solution:
def replaceSpace(self, s: str) -> str:
return s.replace(" ", "%20")
# return '%20'.join(s.split(' '))
6.输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
输入:head = [1,3,2]
输出:[2,3,1]
class Solution:
def reversePrint(self, head: ListNode) -> List[int]:
stack = [] # 递归就好比栈,先进后出
while head:
stack.append(head.val)
head = head.next
return stack[::-1]
7.输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
找根节点在先序中找,找左右子树在中序中找。先递归左子树,因为先序是根左右,所以root+1直接就是左子树的根节点,left是左子树在中序中的起始位置,i-1是左子树在中序中的终止位置。然后递归右子树,因为先序是根左右,找右子树的根节点就要只要左子树的长度就是i-left,再加当前根节点,再加1就是右子树根节点,i+1是右子树在中序中的起始位置,right是右子树在中序中的终止位置。
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
def recur(root, left, right):
# 中止递归的条件
if left > right: return
# 用先序遍历数组root号作为根,生成根节点
# 这是生成树节点的唯一方法,其他都是确定子树的左右边界来辅助生成节点
node = TreeNode(preorder[root])
# 查询根在中序遍历字典中的位置,目的是计算出子树的左右边界
i = dic[preorder[root]]
# 递归左子树,第一个参数用的先序遍历,意思是根,第二三个参数用的中序遍历,意思是子树的左右边界
node.left = recur(root + 1, left, i - 1)
# 递归右子树,同上
node.right = recur(i - left + root + 1, i + 1, right)
return node
dic = {}
preorder = preorder
for i in range(len(inorder)):
# 用字典来存储**中序**遍历数组,用中序来确定左右子树的位置
dic[inorder[i]] = i
return recur(0, 0, len(inorder) - 1)
8.一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
输入:n = 7
输出:21
class Solution:
def numWays(self, n: int) -> int:
a, b = 1, 1
for i in range(n):
a,b = b, a+b
return a % 1000000007
9.把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
输入:[3,4,5,1,2]
输出:1
class Solution:
def minArray(self, numbers: List[int]) -> int:
low, high = 0, len(numbers) - 1
while low < high:
pivot = low + (high - low) // 2
if numbers[pivot] < numbers[high]: # 如果中间值小于最右侧元素说明最小值在中间值左侧
high = pivot
elif numbers[pivot] > numbers[high]: # 如果中间值大于最右侧元素说明最小值在中间值右侧
low = pivot + 1
else:
high -= 1
return numbers[low]
10.给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
输入:board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “ABCCED”
输出:true
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
def dfs(i, j, k):
if not 0 <= i < len(board) or not 0 <= j < len(board[0]) or board[i][j] != word[k]:
return False
if k == len(word) - 1:
return True
board[i][j] = ''
res = dfs(i + 1, j, k + 1) or dfs(i - 1, j, k + 1) or dfs(i, j + 1, k + 1) or dfs(i, j - 1, k + 1)
board[i][j] = word[k]
return res
for i in range(len(board)):
for j in range(len(board[0])):
if dfs(i, j, 0):
return True
return False
11.编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为 汉明重量).)。
输入:n = 11 (控制台输入 00000000000000000000000000001011)
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 ‘1’。
class Solution:
def hammingWeight(self, n: int) -> int:
res = 0
while n:
res += 1 # 统计变量加 1
n &= n - 1 # 消除数字最右边的1
return res
12.输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
cur = dum = ListNode(0)
while l1 and l2:
if l1.val < l2.val:
cur.next, l1 = l1, l1.next
else:
cur.next, l2 = l2, l2.next
cur = cur.next
cur.next = l1 if l1 else l2
return dum.next
13.请完成一个函数,输入一个二叉树,该函数输出它的镜像。
输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]
class Solution:
def mirrorTree(self, root: TreeNode) -> TreeNode:
if not root:
return
stack = [root]
while stack:
node = stack.pop()
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)
node.left, node.right = node.right, node.left
return root
14.请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
def recur(L, R):
if not L and not R:
return True
if not L or not R or L.val != R.val:
return False
return recur(L.left, R.right) and recur(L.right, R.left)
return recur(root.left, root.right) if root else True
15.输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
输入:nums = [1,2,3,4]
输出:[1,3,2,4]
注:[3,1,2,4] 也是正确的答案之一。
class Solution:
def exchange(self, nums: List[int]) -> List[int]:
odd = []
even = []
for num in nums:
if num % 2 == 1:
odd.append(num)
else:
even.append(num)
return odd + even
16.输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.
class Solution:
def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
former, latter = head, head
for _ in range(k):
former = former.next
while former:
former, latter = former.next, latter.next
return latter
17.定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
cur, pre = head, None
while cur:
tmp = cur.next # 暂存后继节点 cur.next
cur.next = pre # 修改 next 引用指向
pre = cur # pre 暂存 cur
cur = tmp # cur 访问下一节点
return pre
18.输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
if not matrix: return []
l, r, t, b, res = 0, len(matrix[0]) - 1, 0, len(matrix) - 1, []
while True:
for i in range(l, r + 1):
res.append(matrix[t][i]) # 从左往右
t += 1
if t > b:
break
for i in range(t, b + 1):
res.append(matrix[i][r]) # 从上往下
r -= 1
if l > r:
break
for i in range(r, l - 1, -1):
res.append(matrix[b][i]) # 从右往左
b -= 1
if t > b:
break
for i in range(b, t - 1, -1):
res.append(matrix[i][l]) # 从下往上
l += 1
if l > r:
break
return res
19.定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.min(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.min(); --> 返回 -2.
class MinStack:
def __init__(self):
self.A, self.B = [], []
def push(self, x: int) -> None:
self.A.append(x)
if not self.B or self.B[-1] >= x:
self.B.append(x)
def pop(self) -> None:
if self.A.pop() == self.B[-1]:
self.B.pop()
def top(self) -> int:
return self.A[-1]
def min(self) -> int:
return self.B[-1]
20.从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root:
return []
res, queue = [], collections.deque()
queue.append(root)
while queue:
tmp = []
for _ in range(len(queue)):
node = queue.popleft()
tmp.append(node.val)
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
res.append(tmp)
return res