LeetCode:386. Lexicographical Numbers & 440. K-th Smallest in Lexicographical Order

在这里插入图片描述

这一题自己始终做不出来,而且找不出来错误在哪儿(这是致命的),但是看了答案又觉得很简单。
自己的思路是这样:
对于一个数,压进去自己之后,再去看它的十倍,对它进行dfs。返回之后再对本身进行往上加,然后dfs:

class Solution {
public:
    vector<int> lexicalOrder(int n) {
        vector<int> ret;
        helper(1, n, ret);
        return std::move(ret);
    }
private:
    void helper(int tempNum, int maxNum, vector<int>& ret) {
        if (ret.size() == maxNum)
            return;
        if (tempNum > maxNum)
            return;
        if (tempNum <= maxNum)
            ret.push_back(tempNum);
        helper(tempNum*10, maxNum, ret);
        int cnt = 1;
        while (ret.size() < maxNum) {
            helper(tempNum + cnt, maxNum, ret);
            ++cnt;
        }
    }
};

报的错误是超时,应该是陷入死循环。可能代码写的有问题,但是感觉思路应该是没错的,所以以后有机会按照这个思路写一下吧。

然后再说从评论区看来的答案,就很简洁明了了:
我们只是对每个数字在它们后面添加从0到9,形成树,然后再去前序遍历,所以:

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

相比之下,自己的思路确实有点复杂了。
然后还有一个迭代的方法,但是有点难以理解,代码先放在这儿,以后再理解吧:

class Solution {
public:
    vector<int> lexicalOrder(int n) {
        vector<int> res(n);
        int cur = 1;
        for (int i = 0; i < n; i++) {
            res[i] = cur;
            if (cur * 10 <= n) {
                cur *= 10;
            } else {
                if (cur >= n) 
                    cur /= 10;
                cur += 1;
                while (cur % 10 == 0)
                    cur /= 10;
            }
        }
        return res;
    }
};

另外一道相关的题目:
在这里插入图片描述
这是当时找实习的时候,头条一面给我出的题。虽然是hard题,但是如果我做出上面的medium方法的话,应该就可以过关了,虽然会超时:

class Solution {
public:
    int findKthNumber(int n, int k) {
        int retNum = -1;
        int cnt = k;
        for (int i = 1; i < 10; ++i) {
            dfs(i, n, retNum, cnt);
            if (retNum != -1)
                return retNum;
        }
        return retNum;
    }
private:
    void dfs(int tempNum, int maxNum, int& retNum, int& cnt) {
        if (tempNum > maxNum)
            return;
        --cnt;
        if (cnt == 0) {
            retNum = tempNum;
            return;
        }
        for (int i = 0; i < 10; ++i) {
            dfs(tempNum*10 + i, maxNum, retNum, cnt);
            if (retNum != -1)
                return;
        }
    }
};

然后下面这个方法没有完全理解,自己写肯定写不出来,之后再理解吧:

public int findKthNumber(int n, int k) {
    int curr = 1;
    k = k - 1;
    while (k > 0) {
        int steps = calSteps(n, curr, curr + 1);
        if (steps <= k) {
            curr += 1;
            k -= steps;
        } else {
            curr *= 10;
            k -= 1;
        }
    }
    return curr;
}
//use long in case of overflow
public int calSteps(int n, long n1, long n2) {
    int steps = 0;
    while (n1 <= n) {
        steps += Math.min(n + 1, n2) - n1;
        n1 *= 10;
        n2 *= 10;
    }
    return steps;
}
posted @ 2019-09-16 10:46  于老师的父亲王老爷子  阅读(6)  评论(0编辑  收藏  举报