本篇为Datawhale组队学习计划第21期LeetCode精选题目组Task09学习笔记。
初学,时间有点仓促,很多解法没有详细分析,未来可能会修改,见谅。
Datawhale学习文档:
https://github.com/datawhalechina/team-learning-program/tree/master/LeetCodeTencent
088 合并两个有序数组
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-sorted-array
给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。
示例:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
思路
参考官方题解(评论区第一条戳中笑点hhh)
看到有序,那就二分法,考虑双指针法,在不确定中试探比较大小。注意题目要求合并到nums1中。
指针分别放在nums1和nums2数组开头,比较最小值后将其放入输出数组中。
官解的图:
优化:若数组从开头开始修改,为避免影响后续数据,nums1的数据需要提前存放(也就相当于新建了一个数组)。改为直接从末尾修改,节省一些空间。
Python实现
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
p1 = m - 1 # p1,p2分别指向两个数组的末尾
p2 = n - 1
p = m + n - 1 # 从末尾开始从小到大填入元素
while p1 >= 0 and p2 >= 0:
if nums1[p1] < nums2[p2]:
nums1[p] = nums2[p2]
p2 -= 1
else:
nums1[p] = nums1[p1]
p1 -= 1
p -= 1
nums1[:p2 + 1] = nums2[:p2 + 1] # 合并
089 格雷编码
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/gray-code
格雷编码是一个二进制数字系统,在该系统中,两个连续的数值仅有一个位数的差异。
给定一个代表编码总位数的非负整数 n,打印其格雷编码序列。即使有多个不同答案,你也只需要返回其中一种。
格雷编码序列必须以 0 开头。
示例:
输入: 2
输出: [0,1,3,2]
输入: 0
输出: [0]
解释:
00 - 0
01 - 1
11 - 3
10 - 2
对于给定的 n,其格雷编码序列并不唯一。
例如,[0,2,3,1] 也是一个有效的格雷编码序列。
00 - 0
10 - 2
11 - 3
01 - 1
此外我们定义格雷编码序列必须以 0 开头。
给定编码总位数为 n 的格雷编码序列,其长度为 2n。当 n = 0 时,长度为 20 = 1。
因此,当 n = 0 时,其格雷编码序列为 [0]。
思路
-
格雷码不唯一,只需要返回一种。题目涉及到数字变化规律(每次只变一位),以及二进制的转化。
参考题解https://leetcode-cn.com/problems/gray-code/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by–12/,动态规划的方法很巧妙。 -
我们使用推导法。每次只变一位,二进制下从左边找到第一个“1”改为“0”即可。
参考:
https://cloud.tencent.com/developer/article/1407014 -
题解中还给出了二进制表达-格雷码的转换式,也可以直接写出代码。
Python实现
(代码比较麻烦但是个人觉得蛮好理解,位操作符知识见文末)
class Solution:
def grayCode(self, n: int) -> List[int]:
res = []
size = 1 << n # 位运算符,二进制下,从右侧推入零来推动最左边的位。
for i in range(size):
res.append((i >> 1) ^ i)
return res
104 二叉树的最大深度
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-depth-of-binary-tree
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回它的最大深度 3 。
思路
官方题解给出递归与广度优先搜索两种方法(其实还有深度优先等等)。
Python实现
递归比较简单(代码开头给出了二叉树的定义)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def maxDepth(self, root: TreeNode) -> int:
if root is None:
return 0
else:
left_height = self.maxDepth(root.left)
right_height = self.maxDepth(root.right)
return max(left_height, right_height) + 1
补充知识
位操作符
https://www.runoob.com/python/python-operators.html
https://www.w3school.com.cn/python/python_operators.asp
<<
左移动运算符:运算数的各二进位全部左移若干位,由 << 右边的数字指定了移动的位数,高位丢弃,低位补0。
如a=60,二进制0011 1100
a << 2 输出结果 240 ,二进制解释: 1111 0000
<<=
赋值运算符,x<<=3,即为x=x<<3
利用这两个算符可以比较方便地进行二进制计算。如本文代码中size=1<<n,若n=4,左移4位,从1到了10000,就是16(高位丢弃,低位补0)