386.字典序排数

174 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

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<=51041 <= n <= 5 * 10^4

思路

不考虑条件:时间复杂度为 O(n) 且使用 O(1) 额外空间的算法。

那么直接将1n1\sim n的数字全部转化为string,然后加入到vector中,当然字符串的长度是很小的,所以排序的复杂度也是接近O(nlogn)O(nlogn),然后再转化为vector<int>即可。

// short int long float double bool char string void
// array vector stack queue auto const operator
// class public private static friend extern 
// sizeof new delete return cout cin memset malloc
// relloc size length memset malloc relloc size length
// for while if else switch case continue break system
// endl reverse sort swap substr begin end iterator
// namespace include define NULL nullptr exit equals 
// index col row arr err left right ans res vec que sta
// state flag ch str max min default charray std
// maxn minn INT_MAX INT_MIN push_back insert
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int>PII;
typedef pair<int, string>PIS;
const int maxn=1e6+50;//注意修改大小
long long read(){long long x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f;}
ll qpow(ll x,ll q,ll Mod){ll ans=1;while(q){if(q&1)ans=ans*x%Mod;q>>=1;x=(x*x)%Mod;}return ans%Mod;}

class Solution {
public:
    vector<int> lexicalOrder(int n) {
        vector<string>a;
        for(int i=1;i<=n;i++){
            string x=to_string(i);
            a.push_back(x);
        }
        sort(a.begin(),a.end());
        vector<int>ans;
        for(auto it:a){
            ans.push_back(stoi(it));
        }
        return ans;
    }
};

接下来考虑条件:时间复杂度为 O(n) 且使用 O(1) 额外空间的算法。

那么对于一个整数nownow,它的下一个字典序整数对应下面的规则:

  • nownow后面附加一个零,即now=now×10now=now\times10,如果nownnow\leq n,那么说明nownow是下一个字典序整数;
  • 否则末尾的数位已经搜索完成,退回上一位,则now=now10now=\lfloor \frac{now}{10} \rfloor,然后继续判断直到now%109&&now+1nnow\%10 \not = 9 \&\&now+1\leq n ,那么nownow是下一个字典序整数。
// short int long float double bool char string void
// array vector stack queue auto const operator
// class public private static friend extern 
// sizeof new delete return cout cin memset malloc
// relloc size length memset malloc relloc size length
// for while if else switch case continue break system
// endl reverse sort swap substr begin end iterator
// namespace include define NULL nullptr exit equals 
// index col row arr err left right ans res vec que sta
// state flag ch str max min default charray std
// maxn minn INT_MAX INT_MIN push_back insert
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int>PII;
typedef pair<int, string>PIS;
const int maxn=1e6+50;//注意修改大小
long long read(){long long x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f;}
ll qpow(ll x,ll q,ll Mod){ll ans=1;while(q){if(q&1)ans=ans*x%Mod;q>>=1;x=(x*x)%Mod;}return ans%Mod;}

class Solution {
public:
    vector<int> lexicalOrder(int n) {
        vector<int>a;
        int now=1;
        for(int i=1;i<=n;i++){
            a.emplace_back(now);
            if(now*10<=n){
                now*=10;
            }
            else{
                while(now%10==9||now+1>n){
                    now/=10;
                }
                now++;
            }
        }
        return a;
    }
};