[Leetcode] 386. Lexicographical Numbers 解题报告

题目

Given an integer n, return 1 - n in lexicographical order.

For example, given 13, return: [1,10,11,12,13,2,3,4,5,6,7,8,9].

Please optimize your algorithm to use less time and space. The input size may be as large as 5,000,000.

思路

1、字符串排序:通过观察可以发现,题目所要求的排序刚好是字典序,我们知道字符串的默认比较函数就是字典序,所以可以首先将[1,n]区间内的数都转换为字符串,然后对字符串数组进行排序,最后再转换回来。这种做法思路最简单,时间复杂度是O(nlogn),但是由于字符串和数字之间的转换比较耗时,所以无法通过大数据测试。

2、非递归版本:我们注意到下一个数往往和上一个数有关系:1)如果上一个数小于等于n的十分之一,那么直接给上一个数乘以10构成下一个数;否则,2)如果上一个数的末尾不是9,那么可以直接给上一个数加1构成下一个数;3)如果上一个数的末尾是9,那么就需要给上一个数除以10再加一了。具体见下面的代码。

3、递归版本:非递归版本的思路很复杂,而且也容易出错,其实递归版本的思路非常清晰和简单。通过分析可以发现,我们按照首位可以将数组区分成为9类(首位为1-9),所以依次进行深度优先搜索即可。每次搜索的过程中,在不超过n的情况下,都试图给当前数的后面加上0-9(注意区分和首位的区别)以构成下一个数。深度优先遍历的顺序保证了加入的数字的顺序是正确的。

代码

1、字符串排序:

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

2、非递归版本:

class Solution {
public:
    vector<int> lexicalOrder(int n) {
        if (n < 1) {
            return {};
        }
        vector<int> res(1, 1);
        while ( res.size() < n ) {
            int last = res[res.size()-1];
            if (last * 10 <= n) {               // need to increase the digit count
                res.push_back(last * 10);
                continue;
            }
            while ( last != 0 ) {
                if ( last % 10 != 9 && last + 1 <= n) { 
                    res.push_back(last + 1);    // normal increase
                    break;
                }
                last /= 10;
            }
        }
        return res;
    }
};

3、递归版本:

class Solution {
public:
    vector<int> lexicalOrder(int n) {
        vector<int> res;
        for (int i = 1; i < 10; ++i) {
            lexicalOrder(i, res, n);
        }
        return res;
    }
private:
    void lexicalOrder(int num, vector<int> &res, int n) {
        if (num > n) {
            return;
        }
        res.push_back(num);
        int t = num * 10;
        for (int i = 0; i < 10; ++i) {
            lexicalOrder(t + i, res, n);
        }
    }
};

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值