剑指offer刷题记录 python3 Java

  • 剑指 Offer 09. 用两个栈实现队列
  • 剑指 Offer 10- I. 斐波那契数列
  • 剑指 Offer 03. 数组中重复的数字
  • 【★】剑指 Offer 04. 二维数组中的查找
  • 剑指 Offer 10- II. 青蛙跳台阶问题
  • 剑指 Offer 11. 旋转数组的最小数字
  • 剑指 Offer 12. 矩阵中的路径
  • 剑指 Offer 05. 替换空格
  • 剑指 Offer 13. 机器人的运动范围
  • 剑指 Offer 06. 从尾到头打印链表
  • 剑指 Offer 07. 重建二叉树
  • 【★】剑指 Offer 14- I. 剪绳子
  • 剑指 Offer 14- II. 剪绳子 II
  • 剑指 Offer 25. 合并两个排序的链表
  • 剑指 Offer 26. 树的子结构
  • 剑指 Offer 27. 二叉树的镜像
  • 剑指 Offer 28. 对称的二叉树
  • 【★】剑指 Offer 20. 表示数值的字符串
  • 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
  • 【★】剑指 Offer 15. 二进制中1的个数
  • 【★】剑指 Offer 29. 顺时针打印矩阵
  • 剑指 Offer 22. 链表中倒数第k个节点
  • 【★】剑指 Offer 16. 数值的整数次方
  • 【★】剑指 Offer 17. 打印从1到最大的n位数
  • 【★】剑指 Offer 19. 正则表达式匹配
  • 剑指 Offer 24. 反转链表
  • 剑指 Offer 18. 删除链表的节点
  • 剑指 Offer 35. 复杂链表的复制
  • 剑指 Offer 40. 最小的k个数

剑指 Offer 09. 用两个栈实现队列

【题目】剑指 Offer 09. 用两个栈实现队列

【思路】

使用两个栈q1、q2:

  • q1用作存储,对于所有的appendTail操作增加的元素都放到q1.append()。
  • q2用作弹出,对于多有的deleteHead操作删除的元素都是q2的pop操作,若q2为空,则将q1的所有元素pop再q2.append(),实现顺序反转,此时q2头部为最先进入的元素。

【代码】

class CQueue:def __init__(self):self.q1, self.q2 = [], []def appendTail(self, value: int) -> None:self.q1.append(value)def deleteHead(self) -> int:if not self.q2:while self.q1:self.q2.append(self.q1.pop())return self.q2.pop() if self.q2 else -1# Your CQueue object will be instantiated and called as such:
# obj = CQueue()
# obj.appendTail(value)
# param_2 = obj.deleteHead()

剑指 Offer 10- I. 斐波那契数列

【题目】剑指 Offer 10- I. 斐波那契数列

【思路】

  • 使用“递归法”会产生大量重复计算,本题使用“动态规划”。
  • 对于取模操作,在加法过程中取模,而不是在结果返回前取模,防止数据越界。

【代码】

class Solution:def fib(self, n: int) -> int:if n == 0:return 0m = int(1e9+7)a, b = 0, 1for _ in range(n - 1):c = bb = (a + b) % ma = creturn b

剑指 Offer 03. 数组中重复的数字

【题目】剑指 Offer 03. 数组中重复的数字

【思路】

采用交换的思想,对于nums = [2, 3, 1, 0, 2, 5, 3],第一次操作转换为nums = [1, 3, 2, 0, 2, 5, 3],即把nums[0] = 2放到对应位置nums[2]上(交换nums[0]和nums[2]),然后第二次操作再把nums[0] = 1放到对应位置nums[1]上,转换为nums = [3, 1, 2, 0, 2, 5, 3] …\dots… 重复操作,知道找到第一个nums[nums[i]] == nums[i]的数。

【代码】

class Solution:def findRepeatNumber(self, nums: List[int]) -> int:for i in range(len(nums)):t = iwhile t != nums[t]:if nums[t] == nums[nums[t]]:return nums[t]nums[nums[t]], nums[t] = nums[t], nums[nums[t]] # python交换赋值为左优先,即先对nums[nums[t]]赋值。nums[nums[t]]和nums[t]位置互换会出错。参考https://stackoverflow.com/questions/21047524/how-does-swapping-of-members-in-tuples-a-b-b-a-work-internally

【★】剑指 Offer 04. 二维数组中的查找

【题目】剑指 Offer 04. 二维数组中的查找

【思路】

  • 矩阵元素排列是有规律的(左至右、上至下为递增),那么共有下列4种搜索方式:

    • 左上角开始,往右递增,往下递增。
    • 右下角开始,往左递减,往上递减。
    • 左下角开始,往右递增,往上递减。
    • 右上角开始,往左递减,往下递增。
  • 只能选取左下角开始右上角开始两种思路。

【代码】

class Solution:def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:if len(matrix) == 0 or len(matrix[0]) == 0:return Falserows, cols = len(matrix), len(matrix[0])row, col = 0, cols - 1while row < rows and col >= 0:if target == matrix[row][col]:return Trueelif target < matrix[row][col]:col -= 1else:row += 1return False

剑指 Offer 10- II. 青蛙跳台阶问题

【题目】剑指 Offer 10- II. 青蛙跳台阶问题

【思路】同【剑指 Offer 10- I. 斐波那契数列】

【代码】略

剑指 Offer 11. 旋转数组的最小数字

【题目】剑指 Offer 11. 旋转数组的最小数字

【思路】

  • 这是一个递增数组的旋转,则有两种情况:

    • 某两个相邻元素为递减(旋转长度 > 0),找到这个递减位置的元素即可;
    • 整个数组为递增(旋转长度 = 0),返回第一个元素。

【代码】

class Solution:def minArray(self, numbers: List[int]) -> int:n = len(numbers)if n < 2:return numbers[0]for i in range(1, len(numbers)):if numbers[i - 1] > numbers[i]:return numbers[i]return numbers[0] # 执行完for循环,但是没有return,说明这是一个递增数组,第一个为最小

剑指 Offer 12. 矩阵中的路径

【题目】剑指 Offer 12. 矩阵中的路径

【思路】

  • 判断是否存在的问题,利用DFS(全部解利用BFS)。
  • 当遍历长度等于str长度时,返回True。
  • 对所有位置遍历一次,防止漏掉正确答案。
  • 当前层遍历完,需要记录遍历过当前位置,这里采用改变内容的方案(也可以使用dp数组)。

【代码】

class Solution:def exist(self, board: List[List[str]], word: str) -> bool:m, n, s = len(board), len(board[0]), len(word)def dfs(i, j, k):if not 0 <= i < m or not 0 <= j < n or board[i][j] != word[k]:return Falseif k == s - 1:return Trueboard[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 resfor i in range(m):for j in range(n):if dfs(i, j, 0):return Truereturn False

剑指 Offer 05. 替换空格

【题目】剑指 Offer 05. 替换空格

【思路】无

【代码】

class Solution:def replaceSpace(self, s: str) -> str:return s.replace(' ', '%20')

剑指 Offer 13. 机器人的运动范围

【题目】剑指 Offer 13. 机器人的运动范围

【思路】

  • 首先有个函数能够实现根据坐标计算和的功能。
  • 利用dfs进行所有位置的遍历,然后利用dp数组保存遍历过的位置。

【代码】

# 求解
def digitsum(n):ans = 0while n:ans += n % 10n //= 10return ansclass Solution:def movingCount(self, m: int, n: int, k: int) -> int:ans = 0dp = [[False] * n for _ in range(m)]def dfs(i, j):if i < m and j < n and not dp[i][j]:nonlocal anstmp = digitsum(i) + digitsum(j)if tmp <= k:dp[i][j] = Trueans += 1dfs(i + 1, j)dfs(i, j + 1)dfs(0, 0)return ans

剑指 Offer 06. 从尾到头打印链表

【题目】剑指 Offer 06. 从尾到头打印链表

【思路】

  • 思路1:遍历一次,放到数组中,然后reverse再return。
  • 思路2:利用递归,到达最末层就向前递归,同时输出当前层的值。

【代码】

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def reversePrint(self, head: ListNode) -> List[int]:ans = []def backtrack(node):if not node:return backtrack(node.next)ans.append(node.val)backtrack(head)return ans

剑指 Offer 07. 重建二叉树

【题目】剑指 Offer 07. 重建二叉树

【思路】

  1. preorder中第一个元素就是root。
  2. 再inorder中找到root对应的位置loc,这个位置左边就是左子树,右边就是右子树。
  3. 递归建树。
  4. 优化:可以利用索引坐标进行建树,这样的话减少了新建list的时间和内存。

【代码】

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:if not preorder:return root = TreeNode(preorder[0])loc = inorder.index(preorder[0])root.left = self.buildTree(preorder[1: loc + 1], inorder[: loc])root.right = self.buildTree(preorder[loc + 1: ], inorder[loc + 1: ])return root

【★】剑指 Offer 14- I. 剪绳子

【题目】剑指 Offer 14- I. 剪绳子

【思路】

  • 当 n≤3n \leq 3n≤3时,按照规则应不切分,但由于题目要求必须剪成m>1段,因此必须剪出一段长度为1的绳子,即返回n−1n - 1n−1。
  • 当 n>3n > 3n>3时,求 n 除以 3 的 整数部分 a 和 余数部分 b(即n=3a+bn = 3a + bn=3a+b),并分为以下三种情况:
    • 当b=0b = 0b=0时,直接返回 3a3^a3a;
    • 当b=1b = 1b=1时,要将一个1+31 + 31+3转换为2+22 + 22+2,因此返回 3a−1×43^{a-1} \times 43a−1×4;
    • 当b=2b = 2b=2时,返回 3a×23^a \times 23a×2。

【代码】

class Solution:def cuttingRope(self, n: int) -> int:if n <= 3: return n - 1a, b = n // 3, n % 3if b == 0: return int(pow(3, a))if b == 1: return int(pow(3, a - 1) * 4)return int(pow(3, a) * 2)

剑指 Offer 14- II. 剪绳子 II

【题目】剑指 Offer 14- II. 剪绳子 II

【思路】

同上。

  • 优化的点:

    • 可以用“快速幂”代替pow()
# 求 (x^a) % p —— 快速幂求余
def remainder(x, a, p):rem = 1while a > 0:if a % 2: rem = (rem * x) % px = x ** 2 % pa //= 2return rem

【代码】

class Solution:def cuttingRope(self, n: int) -> int:if n <= 3: return n - 1a, b, m = n // 3, n % 3, int(1e9+7)if b == 0: return int(pow(3, a, m))if b == 1: return int(pow(3, a - 1, m) * 4 % m)return int(pow(3, a, m) * 2 % m)

剑指 Offer 25. 合并两个排序的链表

【题目】剑指 Offer 25. 合并两个排序的链表

【思路】略。

【代码】

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:dummy = ListNode(0)p = dummywhile l1 and l2:if l1.val < l2.val:p.next = l1l1 = l1.nextelse:p.next = l2l2 = l2.nextp = p.nextif l1:p.next = l1if l2:p.next = l2return dummy.next

剑指 Offer 26. 树的子结构

【题目】剑指 Offer 26. 树的子结构

【思路】

  1. (先序)遍历A,找到与B的根相同的节点,若没找到返回False。
  2. 从相同节点开始dfs(),递归地判断是否为同结构。

【代码】

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool:def dfs(n, m):if not m:return Trueif not n or n.val != m.val:return Falsereturn dfs(n.left, m.left) and dfs(n.right, m.right)return bool(A and B) and (dfs(A, B) or self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B))

剑指 Offer 27. 二叉树的镜像

【题目】剑指 Offer 27. 二叉树的镜像

【思路】交换左右子树,递归同样操作用在左子树和右子树,直到叶子节点。

【代码】

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def mirrorTree(self, root: TreeNode) -> TreeNode:if root:root.left, root.right = root.right, root.leftself.mirrorTree(root.right)self.mirrorTree(root.left)return root

剑指 Offer 28. 对称的二叉树

【题目】剑指 Offer 28. 对称的二叉树

【思路】

利用递归,判断左(右)孩子和对应节点的右(左)孩子是否相等,不相等直接返回,不再递归。

【代码】

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def isSymmetric(self, root: TreeNode) -> bool:def dfs(l: TreeNode, r: TreeNode):if not l or not r:if not l and not r:return Truereturn Falsereturn (l.val == r.val) and dfs(l.left, r.right) and dfs(l.right, r.left)return dfs(root.left, root.right) if root else True

【★】剑指 Offer 20. 表示数值的字符串

【题目】剑指 Offer 20. 表示数值的字符串

【思路】

利用有限状态机解决这个问题,如图。

算法流程:

  1. 初始化:

    1. 状态转移表statesstatesstates:设 states[i]states[i]states[i],其中 iii为所处状态,states[i]states[i]states[i]使用哈希表存储可转移至的状态。键值对(key,value)(key, value)(key,value)含义:若输入keykeykey,则可从状态iii转移至状态valuevaluevalue。
    2. 当前状态ppp:起始状态初始化为p=0p = 0p=0。
  2. 状态转移循环:遍历字符串sss的每个字符ccc。
    1. 记录字符类型ttt:分为四种情况。

      • 当ccc为正负号时,执行t=′s′t = 's't=′s′;
      • 当ccc为数字时,执行t=′d′t = 'd't=′d′;
      • 当ccc为e,Ee , Ee,E时,执行t=′e′t = 'e't=′e′;
      • 当ccc为..., 空格时,执行t=ct = ct=c(即用字符本身表示字符类型);
      • 否则,执行t=′?′t = '?'t=′?′,代表为不属于判断范围的非法字符,后续直接返回FalseFalseFalse 。
    2. 终止条件: 若字符类型ttt不在哈希表states[p]states[p]states[p]中,说明无法转移至下一状态,因此直接返回FalseFalseFalse。
    3. 状态转移: 状态ppp转移至states[p][t]states[p][t]states[p][t]。
  3. 返回值: 跳出循环后,若状态p∈2,3,7,8p \in {2, 3, 7, 8}p∈2,3,7,8,说明结尾合法,返回TrueTrueTrue,否则返回FalseFalseFalse。

【代码】

class Solution:def isNumber(self, s: str) -> bool:states = [{ ' ': 0, 's': 1, 'd': 2, '.': 4 }, # 0. start with 'blank'{ 'd': 2, '.': 4 } ,                # 1. 'sign' before 'e'{ 'd': 2, '.': 3, 'e': 5, ' ': 8 }, # 2. 'digit' before 'dot'{ 'd': 3, 'e': 5, ' ': 8 },         # 3. 'digit' after 'dot'{ 'd': 3 },                         # 4. 'digit' after 'dot' (‘blank’ before 'dot'){ 's': 6, 'd': 7 },                 # 5. 'e'{ 'd': 7 },                         # 6. 'sign' after 'e'{ 'd': 7, ' ': 8 },                 # 7. 'digit' after 'e'{ ' ': 8 }                          # 8. end with 'blank']p = 0                           # start with state 0for c in s:if '0' <= c <= '9': t = 'd' # digitelif c in "+-": t = 's'     # signelif c in "eE": t = 'e'     # e or Eelif c in ". ": t = c       # dot, blankelse: t = '?'               # unknownif t not in states[p]: return Falsep = states[p][t]return p in (2, 3, 7, 8)
# python特性
class Solution:def isNumber(self, s: str) -> bool:try:float(s)return Trueexcept Exception:return False

剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

【题目】剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

【思路】

  1. 利用左右双指针l、rl、rl、r。
  2. 将lll向右移动,找到偶数;将rrr向左移动,找到奇数。
  3. 互换这两个位置的数。
  4. 最终,奇数靠前,偶数靠后。

【代码】

class Solution:def exchange(self, nums: List[int]) -> List[int]:if nums:l, r = 0, len(nums) - 1while l < r:while l < r and nums[l] % 2 == 1:l += 1while l < r and nums[r] % 2 == 0:r -= 1nums[l], nums[r] = nums[r], nums[l]return nums

【★】剑指 Offer 15. 二进制中1的个数

【题目】剑指 Offer 15. 二进制中1的个数

【思路】

  • 利用位运算,每次计算n &= n - 1,这样只会将最后一个1清除掉。
  • n = 0时,说明1都被清除掉了。

也利用Python特点,bin()取得二进制,再str.count()统计'1'的个数。

【代码】

class Solution:# Python 特性# def hammingWeight(self, n: int) -> int:#     return bin(n).count('1')def hammingWeight(self, n: int) -> int:ret = 0while n:n &= n - 1ret += 1return ret

【★】剑指 Offer 29. 顺时针打印矩阵

【题目】剑指 Offer 29. 顺时针打印矩阵

【思路】

  • 可以将矩阵看成若干层,首先打印最外层的元素,其次打印次外层的元素,直到打印最内层的元素。
  • 对于每层,从左上方开始以顺时针的顺序遍历所有元素。假设当前层的左上角位于(top,left)(\textit{top}, \textit{left})(top,left),右下角位于(bottom,right)(\textit{bottom}, \textit{right})(bottom,right),按照如下顺序遍历当前层的元素。
    • 从左到右遍历上侧元素,依次为(top,left)(\textit{top}, \textit{left})(top,left)到(top,right)(\textit{top}, \textit{right})(top,right)。
    • 从上到下遍历右侧元素,依次为(top+1,right)(\textit{top} + 1, \textit{right})(top+1,right)到(bottom,right)(\textit{bottom}, \textit{right})(bottom,right)。
    • 如果left<right\textit{left} < \textit{right}left<right且top<bottom\textit{top} < \textit{bottom}top<bottom,则从右到左遍历下侧元素,依次为(bottom,right−1)(\textit{bottom}, \textit{right} - 1)(bottom,right−1)到(bottom,left+1)(\textit{bottom}, \textit{left} + 1)(bottom,left+1),以及从下到上遍历左侧元素,依次为(bottom,left)(\textit{bottom}, \textit{left})(bottom,left)到(top+1,left)(\textit{top} + 1, \textit{left})(top+1,left)。
  • 遍历完当前层的元素之后,将left\textit{left}left和top\textit{top}top分别增加 11,将right\textit{right}right和bottom\textit{bottom}bottom分别减少 1,进入下一层继续遍历,直到遍历完所有元素为止。

【代码】

class Solution:def spiralOrder(self, matrix: List[List[int]]) -> List[int]:if not matrix or not matrix[0]:return list()rows, columns = len(matrix), len(matrix[0])order = list()left, right, top, bottom = 0, columns - 1, 0, rows - 1while left <= right and top <= bottom:for column in range(left, right + 1):order.append(matrix[top][column])for row in range(top + 1, bottom + 1):order.append(matrix[row][right])if left < right and top < bottom:for column in range(right - 1, left, -1):order.append(matrix[bottom][column])for row in range(bottom, top, -1):order.append(matrix[row][left])left, right, top, bottom = left + 1, right - 1, top + 1, bottom - 1return order

剑指 Offer 22. 链表中倒数第k个节点

【题目】剑指 Offer 22. 链表中倒数第k个节点

【思路】

  1. 设置p、q两个指针,初始值为head;
  2. 让p先向后移动k步;
  3. p、q同时向后移动,直到p==None

【代码】

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:p = q = headif head:for _ in range(k):p = p.nextwhile p:p = p.nextq = q.nextreturn q

【★】剑指 Offer 16. 数值的整数次方

【题目】剑指 Offer 16. 数值的整数次方

【思路】

  1. 利用快速幂的思想。
  2. 当n<0n < 0n<0时:把问题转化至n≥0n \geq 0n≥0的范围内,即执行x=1/x,n=−nx = 1/x,n = - nx=1/x,n=−n;
  3. 循环计算:当n=0n = 0n=0时跳出;
    1. 当n&1=1n \& 1 = 1n&1=1时:将当前xxx乘入resresres(即res∗=xres *= xres∗=x);
    2. 执行x=x2x = x^2x=x2(即x∗=xx *= xx∗=x);
    3. 执行nnn右移一位(即n>>=1n >>= 1n>>=1)。

【代码】

class Solution:def myPow(self, x: float, n: int) -> float:if x == 0: return 0res = 1if n < 0: x, n = 1 / x, -nwhile n:if n & 1: res *= xx *= xn >>= 1return res

【★】剑指 Offer 17. 打印从1到最大的n位数

【题目】剑指 Offer 17. 打印从1到最大的n位数

【思路】

  1. range()解决,但不兼容大数
  2. 解决大数问题:
    1. 变量类型使用string
    2. 生成数字字符集,通过递归完成nnn位0−90 - 90−9的全排列
    3. 解决高位的000,并且让列表从111开始。

【代码】

class Solution:# 非大数def printNumbers(self, n: int) -> List[int]:return list(range(1, 10 ** n))# 大数def printNumbers(self, n: int) -> [int]:def dfs(x):if x == n:s = ''.join(num[self.start:])if s != '0': res.append(int(s))if n - self.start == self.nine: self.start -= 1returnfor i in range(10):if i == 9: self.nine += 1num[x] = str(i)dfs(x + 1)self.nine -= 1num, res = ['0'] * n, []self.nine = 0self.start = n - 1dfs(0)return res

【★】剑指 Offer 19. 正则表达式匹配

【题目】剑指 Offer 19. 正则表达式匹配

【思路】

我们用f[i][j]f[i][j]f[i][j]表示sss的前iii个字符与ppp中的前jjj个字符是否能够匹配。在进行状态转移时,我们考虑ppp的第jjj个字符的匹配情况:

  • 如果ppp的第jjj个字符是一个小写字母,那么我们必须在sss中匹配一个相同的小写字母,即
    f[i][j]={f[i−1][j−1],s[i]=p[j]False,s[i]≠p[j]f[i][j]= \begin{cases} f[i - 1][j - 1] & , {s[i] = p[j]}\\ False & , {s[i] \neq p[j]} \end{cases} f[i][j]={f[i−1][j−1]False​,s[i]=p[j],s[i]​=p[j]​
    也就是说,如果sss的第iii个字符与ppp的第jjj个字符不相同,那么无法进行匹配;否则我们可以匹配两个字符串的最后一个字符,完整的匹配结果取决于两个字符串前面的部分。
  • 如果ppp的第jjj个字符是*,那么就表示我们可以对ppp的第j−1j−1j−1个字符匹配任意自然数次。
    • 匹配sss末尾的一个字符,将该字符扔掉,而该组合还可以继续进行匹配;
    • 不匹配字符,将该组合扔掉,不再进行匹配。
      f[i][j]={f[i−1][j]orf[i][j−2],s[i]=p[j−1]f[i][j−2],s[i]≠p[j−1]f[i][j]= \begin{cases} f[i - 1][j] \space or \space f[i][j - 2] & , {s[i] = p[j - 1]}\\ f[i][j - 2] & , {s[i] \neq p[j - 1]} \end{cases} f[i][j]={f[i−1][j] or f[i][j−2]f[i][j−2]​,s[i]=p[j−1],s[i]​=p[j−1]​
  • 在任意情况下,只要p[j]p[j]p[j]是.,那么p[j]p[j]p[j]一定成功匹配sss中的任意一个小写字母。

最终的状态转移方程如下:
f[i][j]={if(p[j]≠‘∗’)={f[i−1][j−1],matches(s[i],p[j])False,otherwiseotherwise={f[i−1][j]orf[i][j−2],matches(s[i],p[j−1])f[i][j−2],otherwisef[i][j]= \begin{cases} if (p[j] \neq ‘*’) = \begin{cases} f[i - 1][j - 1] & ,{matches(s[i], p[j])}\\ False & ,{otherwise} \end{cases} \\ otherwise = \begin{cases} f[i - 1][j] \space or \space f[i][j - 2] & ,{matches(s[i], p[j - 1])}\\ f[i][j - 2] & ,{otherwise} \end{cases} \end{cases} f[i][j]=⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧​if(p[j]​=‘∗’)={f[i−1][j−1]False​,matches(s[i],p[j]),otherwise​otherwise={f[i−1][j] or f[i][j−2]f[i][j−2]​,matches(s[i],p[j−1]),otherwise​​
其中matches(x,y)\textit{matches}(x, y)matches(x,y)判断两个字符是否匹配的辅助函数。只有当yyy是.或者xxx和yyy本身相同时,这两个字符才会匹配。

【代码】

class Solution:def isMatch(self, s: str, p: str) -> bool:m, n = len(s), len(p)def matches(i: int, j: int) -> bool:if i == 0:return Falseif p[j - 1] == '.':return Truereturn s[i - 1] == p[j - 1]f = [[False] * (n + 1) for _ in range(m + 1)]f[0][0] = Truefor i in range(m + 1):for j in range(1, n + 1):if p[j - 1] == '*':f[i][j] |= f[i][j - 2]if matches(i, j - 1):f[i][j] |= f[i - 1][j]else:if matches(i, j):f[i][j] |= f[i - 1][j - 1]return f[m][n]

剑指 Offer 24. 反转链表

【题目】剑指 Offer 24. 反转链表

【思路】

递归 or 迭代。

【代码】

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None# 迭代
class Solution:def reverseList(self, head: ListNode) -> ListNode:if not head:return headpre, p = None, headwhile p.next:nxt = p.nextp.next = prepre = pp = nxtp.next = prereturn p
# 递归
class Solution:def reverseList(self, head: ListNode) -> ListNode:if not head or not head.next:return headnewhead = self.reverseList(head.next)head.next.next = headhead.next = Nonereturn newhead

剑指 Offer 18. 删除链表的节点

【题目】剑指 Offer 18. 删除链表的节点

【思路】略。

【代码】

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:def deleteNode(self, head: ListNode, val: int) -> ListNode:if not head:return headdummy = ListNode(0)dummy.next = headp = dummywhile p and p.next:if p.next.val == val:p.next = p.next.nextp = p.nextreturn dummy.next

剑指 Offer 35. 复杂链表的复制

【题目】剑指 Offer 35. 复杂链表的复制

【思路】

穿针引线法。
对于链表A→B→CA→B→C,我们可以将其拆分为A→A′→B→B′→C→C′。对于任意一个原节点S,其拷贝节点S′即为其后继节点。对于链表 A \rightarrow B \rightarrow CA→B→C,我们可以将其拆分为 A \rightarrow A' \rightarrow B \rightarrow B' \rightarrow C \rightarrow C'。对于任意一个原节点 S,其拷贝节点 S'即为其后继节点。 对于链表A→B→CA→B→C,我们可以将其拆分为A→A′→B→B′→C→C′。对于任意一个原节点S,其拷贝节点S′即为其后继节点。
然后再进行遍历,将random域next域修正即可。

【代码】

/*
// Definition for a Node.
class Node {int val;Node next;Node random;public Node(int val) {this.val = val;this.next = null;this.random = null;}
}
*/
class Solution {public Node copyRandomList(Node head) {if (head == null) {return null;}for (Node node = head; node != null; node = node.next.next) {Node nodeNew = new Node(node.val);nodeNew.next = node.next;node.next = nodeNew;}for (Node node = head; node != null; node = node.next.next) {Node nodeNew = node.next;nodeNew.random = (node.random != null) ? node.random.next : null;}Node headNew = head.next;for (Node node = head; node != null; node = node.next) {Node nodeNew = node.next;node.next = nodeNew.next;nodeNew.next = (nodeNew.next != null) ? nodeNew.next.next : null;}return headNew;}
}

剑指 Offer 40. 最小的k个数

【题目】剑指 Offer 40. 最小的k个数

【思路】

  1. 方法一:
    维护一个size=ksize = ksize=k的大顶堆,插入数据的过程中,size>ksize > ksize>k就取掉顶部元素(最大元素)。
  2. 方法二:
    利用快排思想,当一次划分partition()后,基准元素位置在第k个位置,则该位置之前的元素是数组中最小的k个值。

【代码】

// 堆
class Solution {public int[] getLeastNumbers(int[] arr, int k) {int[] vec = new int[k];if (k == 0) {return vec;}PriorityQueue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>() {public int compare(Integer n1, Integer n2) {return n2 - n1; // 大顶堆 (小顶堆是n1 - n2)}});for (int i = 0; i < k; ++i) {queue.offer(arr[i]);}for (int i = k; i < arr.length; ++i) {if (queue.peek() > arr[i]) {queue.poll();queue.offer(arr[i]);}}for (int i = 0; i < k; ++i) {vec[i] = queue.poll();}return vec;}
}
// 快排
class Solution {public int[] getLeastNumbers(int[] arr, int k) {if (k == 0) {return new int[]{};}return Arrays.copyOfRange(arr, 0, quickSort(arr, 0, arr.length - 1, k - 1) + 1);}public int quickSort(int[] nums, int l, int r, int index) {int q = partition(nums, l, r);if (q == index) {return q;}return (q > index) ? quickSort(nums, l, q - 1, index) : quickSort(nums, q + 1, r, index);}public int partition(int[] nums, int l, int r) {int x = nums[r], i = l - 1;for (int j = l; j < r; ++j) {if (nums[j] < x) {swap(nums, ++i, j);}}swap(nums, i + 1, r);return i + 1;}public void swap(int[] nums, int i, int j) {int tmp = nums[i];nums[i] = nums[j];nums[j] = tmp;}
}

剑指offer刷题记录 python3 Java相关推荐

  1. 剑指offer刷题总记——Java

    剑指offer JZ1 二维数组中的查找 JZ2 替换空格 JZ3 从尾到头打印链表 JZ4 重建二叉树 JZ5 用两个栈实现队列 JZ6 旋转数组的最小数字 JZ7 斐波那契数列 JZ8 跳台阶 J ...

  2. 剑指offer刷题记录(上)

    记录刷题过程,方便自己后期回顾 题目来自<剑指offer>,在牛客上OC,思路大多来自剑指offer,偶尔来自自己的碎碎念,代码自己瞎写的,如果有更优的方法请告诉我,谢谢大佬们 语言:py ...

  3. 剑指Offer 刷题记录

    文章目录 剑指offer题目 01. 二维数组中的查找 02. 替换空格 03. 从尾到头打印链表 04. 重建二叉树 05. 两个堆栈模拟一个队列 06. 旋转数组的最小数字 07. 斐波那契数列 ...

  4. 力扣(LeetCode)剑指offer刷题笔记(java),已完结!!!

    文章目录 3.数组中重复的数字 4.二维数组中的查找 5.替换空格 6.从尾到头打印链表 7.重建二叉树 9.两个栈来实现一个队列 10-1.斐波那契数列 10-2.跳台阶 11.旋转数组的最小数字 ...

  5. string类函数和牛客网剑指offer刷题记录

    1.strcat char* strcat(char *strDest,const char *strSrc){assert(strDest && strSrc);char *p = ...

  6. 【LeetCode 剑指offer刷题】回溯法与暴力枚举法题6:Number of Islands

    [LeetCode & 剑指offer 刷题笔记]目录(持续更新中...) Number of Islands Given a 2d grid map of '1's (land) and ' ...

  7. 【LeetCode 剑指offer刷题】树题6:28 对称二叉树(101. Symmetric Tree)

    [LeetCode & 剑指offer 刷题笔记]目录(持续更新中...) 101. Symmetric Tree /**  * Definition for a binary tree no ...

  8. 【LeetCode 剑指offer刷题】数组题2:57 有序数组中和为s的两个数(167 Two Sum II - Input array is sorted)...

    [LeetCode & 剑指offer 刷题笔记]目录(持续更新中...) 57 有序数组中和为s的两个数 题目描述 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是 ...

  9. 【LeetCode 剑指offer刷题】字符串题6:67 把字符串转成整数

    [LeetCode & 剑指offer 刷题笔记]目录(持续更新中...) 67 把字符串转成整数 题目描述 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数. 数值为0或者字符 ...

最新文章

  1. 当当网强烈谴责李国庆有关刘强东案言论
  2. AI也能写高考作文?我们用清华刚刚开源的「九歌」试了试
  3. 【C++】vs无法更新DoDataExchange方法问题解决
  4. windows API 开发飞机订票系统 图形化界面 (二)
  5. 后端技术:ELK不香了?企业级日志平台新框架 Graylog介绍
  6. REST和RESTful有什么区别
  7. DDR3 MIG IP核仿真与学习
  8. 推荐几款好用的编程字体
  9. 【毕设笔记】轴承振动数据故障诊断软件系统
  10. Photoshop 2020 新建文档窗口闪烁,点击创建按钮无效的解决办法(继续使用新版)
  11. css 1倍图 2倍图 3倍图
  12. 【超详细word排版】页眉:宋体五号,居中排列。左面页眉为论文题目,右面页眉为章次和章标题。页眉底划线的宽度为0.75磅。 页码:宋体小五号,排在页眉行的最外侧,不加任何修饰。
  13. Pascal与C的指针
  14. c语言程序设计李丽娟pdf,C语言程序设计教程 教学课件 李丽娟 第5章循环结构.pdf...
  15. 车载注册蓝牙服务器,蓝牙配对码配备方法、系统、终端、服务器及车载设备专利_专利查询 - 天眼查...
  16. windows server 2003 系列号
  17. Java的垃圾回收机制详解——从入门到出土,学不会接着来砍我!
  18. 深入解读DAMA-DMBOK2
  19. STM32 低功耗设计
  20. 8255交通灯实验的微型计算机,微机原理实验四实验报告8255控制交通灯实验

热门文章

  1. Android dump使用
  2. asp:boundfield html,设置文本格式在ASP.Net的BoundField
  3. win10升级后怎么激活office2013?win10系统office2013激活妙招
  4. CentOS6.8下nodejs环境安装
  5. bugkuCTF之这是一张简单的图片
  6. 中睿天下亮相2022电力行业信息化年会
  7. win10系统下duet display
  8. VirtualBox 共享文件夹设置
  9. 加法天才(高精度加法)
  10. Android SDK 无法更新或更新慢解决方法