738.单调递增的数字
当且仅当每个相邻位数上的数字 x
和 y
满足 x <= y
时,我们称这个整数是单调递增的。
给定一个整数 n
,返回 小于或等于 n
的最大数字,且数字呈 单调递增 。
示例 1:
输入: n = 10 输出: 9
示例 2:
输入: n = 1234 输出: 1234
示例 3:
输入: n = 332 输出: 299
这个题其实很简单,用贪心思路,如果遇到不是递增的,我们把这位置变成9,前面一位减去1。
只不过这个题你要看遍历顺序。
一种常规的思路就是,我从后往前遍历。如果遇到不是递增的,我把当前不是递增及其后面的元素全部变成9,前面一位的数字减去1。就可以了,这个思路是简洁的,也是大部分参考答案的版本,代码如下。
def monotoneIncreasingDigits(self, n: int) -> int:
str_list = list(str(int))
for i in range(len(str_list)-1, 0, -1):
if str_list[i-1] > str_list[i]:
str_list[i-1] = str(int(str_list[i-1]) -1)
str_list[i:] = "9" * (len(str_list) - i )
return int("".join(strNum))
在没看参看答案之前,我自己也做出来,但思路有一点不一样。我是先从左向右遍历。如果他是递增,那我直接返回;如果发现有元素不是递增,我记录这个不是递增的index,我记录为break_point, 并中止遍历。
那么在break_point及其以后的数字都应该赋值为9
那么接下来我就该处理[0, break_point-1]这个区间的元素。
我在这里已经找到[0, break_point-1]这个数字肯定是非递减的,但是可能存在重复元素,比如122
我们从右向左遍历,如果发现 后一个元素大于前一个元素,那么我们可以直接在后一个元素减去1,然后直接跳出循环;但是如果后一个元素等于前一个元素,那就又得分情况考虑。如果前一个元素不是队首元素,那么我们得让后一个元素变成9【因为你们相等 你减去1 那么于前面得冲突了】,索引继续移动;如果是队首元素,我们是让队首元素减去1。
def monotoneIncreasingDigits(n: int) -> int:
str_n = list(str(n))
if len(str_n) <= 1:
return n
flag = True
break_index = 0
for i in range(1, len(str_n)):
if str_n[i] < str_n[i-1]:
flag = False
break_index = i
break
if flag:
return n
else:
# 断点之后的都应该为9 这没问题
for i in range(break_index, len(str_n)):
str_n[i] = '9'
# 那么就要操作前面了
# 涉及到首位的问题
# if len(str_n) - break_index < 2:
# str_n[0] = str(int(str_n[0])-1)
# return int(''.join(str_n))
if break_index -2 < 0:
str_n[0] = str(int(str_n[0])-1)
return int(''.join(str_n))
for i in range(break_index-2, -1, -1):
# 从break_point开始的 说明钱买你是非递减 如果一来就直接 i < i+1了 那就可以结束了 因为i+1肯定是可以减去1的
if str_n[i] < str_n[i+1]:
str_n[i+1] = str(int(str_n[i+1])-1)
break
elif str_n[i] == str_n[i+1] and i !=0:
str_n[i+1] = '9'
elif str_n[i] == str_n[i+1] and i == 0:
str_n[i+1] = '9'
str_n[i] = str(int(str_n[i])-1)
else:
break
return int(''.join(str_n))
贪心总结
感觉就是没有规律。有些简单得贪心你很容易想到思路
有些是就是想不到。
多练习 多刷
特别是最大子序和