每日算法 - 找出[1,n]范围内按照字典排序的最小第k个值

2019/03/27

找出[1,n]范围内按照字典排序的最小第k个值

1.题目描述

输入正整数n和k,n>=k,找出[1,n]范围内按照字典排序的最小第k个值。
输入两个正整数n,k
输出一个整数数
实例:
输入:15,3
输出:11

2.题目分析

何为字典顺序?
即,若比较158 和 26,先比较第一个数字,1<2,则125<26
       若比较243和257先比较第一个数字2=2,在比较第二个数字4<5,即243<257
顺序如下
       10 ,100, 11, 12, 13, 14,15,16,17,18,19,2,20,21,22,23......

3.代码

trie树,建立10叉树

思路1

public static int lexicalOrder(int n , int k ) {
        int curr = 1;
        k--;
        for (int i = 1; i <= n && k>0; i++) {
            if (curr * 10 <= n) {
                curr *= 10;
            } else if (curr % 10 != 9 && curr + 1 <= n) {
                curr++;
            }else {
                while ((curr / 10) % 10 == 9) {
                    curr /= 10;
                }
                curr = curr / 10 + 1;
            }
            k--;
        }
        return curr;
    }
思路: 如下注释
比如199 10 字符的变化是 1 10 100 101 102 .. 109 11 110 ..

所以可以看出变化的第一步是 x 10
而第二步,100 x 10 > 199, 这时候是个位开始 +1 所以就是 +1
第三步: 109 下一步加1就会有进位, 110 但下一个应该是 11 所以 109 / 10 + 1
第四步: 199 下一步不是20020 而是2 故循环判断9 等于9就除一次10,知道十位不为9

def k_order(n, k)
  curr = 1
  k -= 1

  index = 1
  while (index <= n && k > 0) do
    # 字符串递增是后缀加0的顺序,所以递增的时候是先x10
    if curr * 10 <= n
      curr *= 10
    # 个位不为9是排除进位,个位加1是下一阶段的字符递增
    elsif curr % 10 != 9 && curr + 1 <= n
      curr += 1
    else
      # 除以10是去掉个位,然后判断十位,如果是9继续循环
      # 因为 +1 会进位, 如 199 / 10 = 19
      # 不操作的结果是 199 / 10 + 1 = 20  实际应该是2的
      while (curr / 10) % 10 == 9 do
        curr /= 10
      end
      curr = curr / 10 + 1
     end

     k -= 1
     index += 1
  end
  return curr
end


Show Disqus Comments

Post Directory