本周题目不太难。
第一题 5315. 6 和 9 组成的最大数字
简单题。
直接遍历把第一个 6 改成 9 就行。
用 python 很方便,但是需要注意 python 的字符串是不可变的,需要转成 list 方便操作(当然我是从 int 转成 str 再转成了 list)
class Solution:
def maximum69Number (self, num: int) -> int:
x = list(str(num))
for i in range(len(x)):
if x[i] == '6':
x[i] = '9'
break
return int(''.join(x))
在题目评论里看到别人的解法,太强了
class Solution:
def maximum69Number (self, num: int) -> int:
return int(str(num).replace('6','9',1))
第二题 5316. 竖直打印单词
这个远远没有题库里的第 6 题 Z 字形变换 难,这题很靠前,估计很多人都做过吧。
本题目尤其用 python 方便,连去结尾空格都有函数。
class Solution:
def printVertically(self, s: str) -> List[str]:
s = s.split(' ')
max_l = 0
for w in s:
max_l = max(max_l, len(w))
r = [[] for i in range(max_l)]
for w in s:
for i in range(max_l):
if i < len(w):
r[i].append(w[i])
else:
r[i].append(' ')
rr = []
for x in r:
rr.append(''.join(x).rstrip())
return rr
第三题 5317. 删除给定值的叶子节点
本题比赛中的示例 5 刚开始是有问题的:
示例 5:输入:root = [1,2,3], target = 2
输出:[1,2,3]
让我犹豫了一会。
后来这个 target 改成 1 就对了。
也不难
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def removeLeafNodes(self, root: TreeNode, target: int) -> TreeNode:
def del_t(t):
if t.left:
if del_t(t.left):
t.left = None
if t.right:
if del_t(t.right):
t.right = None
if not t.left and not t.right:
if t.val == target:
return True
return False
if del_t(root):
return None
return root
第四题 5318. 灌溉花园的最少水龙头数目
这题目 18 年初实习面试的时候被问过。线段覆盖问题。贪心算法。面试的时候我想的使用递归方法,这次写的是迭代。
思路是:
先把每个水龙头的范围转化成区间,弄成一个区间数组。
比如 示例 1
转换成:
[[0, 3], [0, 5], [1, 3], [2, 4]]
这里做了两个优化:
- 长度为零的就忽略了
- 超出 0 到 n 范围的就截止到 [0, n] 区间内
然后我们可以在按照区间的左端点排序。(上面的数组已经是这个顺序了)
其实另外还有一个优化:如果一个区间被另一个区间完全覆盖了,那这个区间也是无效的,应该删掉,例如 [1, 3] 完全落在 [0, 3] 内。
结果这里就只剩下 [0, 5] 了:
[[0, 5]]
所以这个例子不好,可以看下示例 3
n = 7, ranges = [1,2,1,0,2,1,0,1]
经过上述操作后剩下的区间其实也只有刚好三个了:
[(0, 3), (2, 6), (6, 7)]
所以干脆去掉
之后的做法是:
如果这个区间数量是 0 或者第一个区间不能覆盖 0,直接返回 -1
然后就开始贪心:
- 第一个区间必选,ans 变量计已选的区间数
- 判断是否可以覆盖,如果可以,返回 ans
- 从下一个区间开始,所有可以选择的区间(如果这个区间的左端点小于等于上一个选中区间的右端点,就可以选)中找一个右端点最大的,选择,如果没有可选的,返回 -1
这个代码写的不够精炼
class Solution:
def minTaps(self, n: int, ranges: List[int]) -> int:
# ranges 转化为区间
seg = []
for i in range(n+1):
if ranges[i] > 0:
seg.append((max(0, i - ranges[i]), min(n, i + ranges[i])))
# 去掉被其他区间覆盖的区间
s2 = {}
for s in seg:
if s[0] not in s2:
s2[s[0]] = []
s2[s[0]].append(s)
seg = []
for k in s2:
t = s2[k][0]
for xx in s2[k]:
if xx[1] > t[1]:
t = xx
seg.append(t)
s2 = {}
for s in seg:
if s[1] not in s2:
s2[s[1]] = []
s2[s[1]].append(s)
seg = []
for k in s2:
t = s2[k][0]
for xx in s2[k]:
if xx[0] < t[0]:
t = xx
seg.append(t)
seg.sort(key=lambda x: x[0]) # 按区间左端点排序
if not seg or seg[0][0] != 0: # 区间数量是 0 或者第一个区间不能覆盖 0,直接返回 -1
return -1
i = 0
ans = 1
while seg[i][1] != n:
nx = i
j = 1 + i
while j < len(seg) and seg[j][0] <= seg[i][1]:
if seg[nx][1] < seg[j][1]:
nx = j
j += 1
if nx == i:
return -1
ans += 1
i = nx
return ans
谢谢阅读
欢迎访问我的博客 https://codeplot.top/
我的博客的刷题分类
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。