738. 单调递增的数字-贪心算法
题目描述
leetcode题目链接
当且仅当每个相邻位数上的数字 x 和 y 满足 x <= y 时,我们称这个整数是单调递增的。
给定一个整数 n ,返回 小于或等于 n 的最大数字,且数字呈 单调递增 。
示例 1:
输入: n = 10
输出: 9
示例 2:
输入: n = 1234
输出: 1234
示例 3:
输入: n = 332
输出: 299
思路
一旦出现strNum[i - 1] > strNum[i]的情况(非单调递增),首先想让strNum[i - 1]–,然后strNum[i]给为9,比如98,这样得到89就是小于98的最大的单调递增整数。
然后要考虑遍历顺序,要得到最大数字,就尽量不动左边的高位数字,所以想到从右往左遍历。
C++代码
错误版本
class Solution {
public:
int monotoneIncreasingDigits(int n) {
string str = std::to_string(n);
for(int i = str.size()-1; i > 0; i--){ //string对象的长度
if(str[i - 1] > str[i]){
str[i - 1]--;
str[i] = '9';
}
}
return stoi(str); //string转int
}
};
但是这样在一些例子是错误的,比如100,从右往左比较0和是单调递增的,所以不变,返回90,但实际结果应该是99。
所以刚刚忽略了一点,就是如果某一位减1的话,后面的全部都是9。
正确版本
class Solution {
public:
int monotoneIncreasingDigits(int n) {
string str = std::to_string(n);
int index = str.size(); //用来标志减1的位
for(int i = str.size()-1; i > 0; i--){ //string对象的长度
if(str[i - 1] > str[i]){
str[i - 1]--;
index = i-1;
}
}
for(int i = index + 1; i < str.size(); i++){
str[i] = '9';
}
return stoi(str); //string转int
}
};
涉及编程知识碎片
C++标准库中的数据类型转换函数
1、字符串转数字
stoi()
作用是将 n 进制的字符串转化为十进制,使用时包含头文件string
定义如下:
int stoi( const std::string& str, std::size_t* pos = nullptr, int base = 10 );
参数:
str - 待转换的字符
pos - 其取值可以是一个空字符,在这种情况下,pos未被使用;另外如果pos不是空指针,函数将pos的值设置为str中数字后面的第一个字符的位置。
base - 字符中数字的进制,默认为10进制,如果base取值为0,则进制由字符串中的格式决定。
返回值:
如果转换成功的话,stoi函数将会把转换后的得到数字以int类型返回。
如果字符串中没有数字的话,将会抛出"invalid_argument"的异常;
如果字符串中的数字转换后超过int的范围,将会抛出"out_of_range"的异常;
因此使用stoi函数的时候最好加入异常处理。
2、数字转字符串
std::to_string()
java代码
class Solution {
public int monotoneIncreasingDigits(int n) {
//数字转字符串
String numstr = String.valueOf(n);
//转数组
String[] nums = numstr.split("");
String result;
int index = nums.length; //标记哪一位需要被减1
//从后向前遍历比较
for(int i = nums.length - 1; i > 0; i--){
if(Integer.parseInt(nums[i]) < Integer.parseInt(nums[i-1])){
index = i-1;
nums[i -1] = String.valueOf(Integer.parseInt(nums[i - 1]) - 1);
}
}
for(int i = index + 1; i < nums.length; i++){
nums[i] = "9";
}
//拼接字符串
result = String.join("",nums);
//转数字
return Integer.parseInt(result);
}
}
涉及编程知识碎片
- String & int类型转换
- String的常用方法–分割、拼接