持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情
题目
题目链接:力扣386:字典序排数
给你一个整数 n ,按字典序返回范围 [1, n] 内所有整数。
你必须设计一个时间复杂度为 O(n) 且使用 O(1) 额外空间的算法。
示例 1:
输入:n = 13
输出:[1,10,11,12,13,2,3,4,5,6,7,8,9]
示例 2:
输入:n = 2
输出:[1,2]
提示:
1 <= n <= 5 * 10^4
解题思路
👉调用函数
这种方法主要是调用库函数解决,由于 C++ 的 sort 函数可以排序几乎任何类型的数组,所以包括 string ,而对 string 类型的排序是字典序排序。所以可以把数字转换为字符串类型,再对其进行 sort 排序,之后将其赋给 int 型数组即可。但用这种方法不满足题意,题目要求使用 O(1) 的额外空间算法,所以可以用常规方法。
转换函数:
- 数字转换为字符串:
to_string() - 字符串转换为数字:
stoi()
👉常规解法
题目没有为难人,只让我们输出从 1到 n的字典序。所以可以发现一个规律(比如n=110):
[1,10,100,101,...109,11,110,12,13,14,...]
由于字典序的排序是第一个字母的权重最大,依次向后递减的。当前面的数字相等时,判断后面数字的大小,大的放后面,小的放前面。所以利用这个特点可以有如下思路:
nums[i] = cur;
if (cur * 10 <= n)
cur *= 10;
else {
if (cur >= n)
cur /= 10;
cur ++;
while (cur % 10 == 0)
cur /= 10;
}
再加上一个循环和 cur的初值就是这题的完整代码了。
代码(C++)
方法一
class Solution {
public:
vector<int> lexicalOrder(int n) {
vector<int> nums;
vector<string> str;
for (int i = 1; i <= n; ++ i)
str.push_back(to_string(i));
sort(str.begin(), str.end());
for (int i = 0; i < n; ++ i)
nums.push_back(stoi(str[i]));
return nums;
}
};
方法二
class Solution {
public:
vector<int> lexicalOrder(int n) {
vector<int> nums(n);
int cur = 1;
for (int i = 0; i < n; ++ i) {
nums[i] = cur;
if (cur * 10 <= n)
cur *= 10;
else {
if (cur >= n)
cur /= 10;
cur ++;
while (cur % 10 == 0)
cur /= 10;
}
}
return nums;
}
};
总结
拿到题目的第一思路就是使用函数解决,但是有些函数在有些比赛或面试中是不允许使用的,所以最好使用最常规的方法解题。本题的常规方法能想到不容易,但如果慢慢调试应该可以写出来。
不论是函数还是常规方法都应该掌握,函数更便捷,常规方法更锻炼思维。