【每日一题】力扣386 字典序排数


题目

题目链接:力扣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()

👉常规解法

题目没有为难人,只让我们输出从 1n的字典序。所以可以发现一个规律(比如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;
    }
};

总结

拿到题目的第一思路就是使用函数解决,但是有些函数在有些比赛或面试中是不允许使用的,所以最好使用最常规的方法解题。本题的常规方法能想到不容易,但如果慢慢调试应该可以写出来。

不论是函数还是常规方法都应该掌握,函数更便捷,常规方法更锻炼思维。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

聆听逝去的流

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值