[leetcode-400]辞書式順序でK番目に小さい数字

トピック

指定された整数の合計  で  辞書式  に  最小の数値を返します   n  。  k[1, n]k

例1

输入: n = 13, k = 2
输出: 10
解释: 字典序的排列是 [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9],所以第二小的数字是 10。

复制代码

例2

输入: n = 1, k = 1
输出: 1
复制代码

ヒント

  • 1 <= k <= n <= 109

答え

問題が単純であるほど、問題は大きくなります。問題は1文であり、問​​題は長い間解決されます。

ポリツリーのプレオーダートラバーサル


graph TD
root --> 1
root --> 2
root --> 3[...]
root --> 9
1 --> 10
1 --> 11
1 --> 12[...]
1 --> 19
10 --> 100
10 --> 101
10 --> 102[...]
10 --> 109

  • 1からnまでの辞書式順序は、上記の不完全な9項ツリーのノードと見なすことができます。
  • 上記の9元ツリーノードからプレオーダーでトラバースされたk番目のノードは、辞書式順序でk番目に小さい数です。

上記の写真とテキストは解決策のアイデアを与えています、以下はアイデアをコードに変換することです

  • 1からnまでの9項ツリーを直接構築することは可能ですか?はい、はい、しかし複雑さは少し高いです。k番目のツリーを見つけるだけで、完全なツリーを構築する必要があります。これは失う価値がありません。
  • ツリーの特性を使用して、プレオーダートラバーサルをシミュレートし、時間の複雑さを軽減できます。

シミュレートする方法は?

  • getChildrenメソッドがある場合は、現在のノードの下に子ノードがいくつあるかを取得できます。

    • たとえば、1から100まで、1の下に12のノードがあります。
  • 子ノードの数childがk未満であると想定します

    • 現在のノードにすべての子ノードが含まれていると言うのは答えではありません。答えは、現在のノードの他の兄弟にあります。
    • kから子を引いたもの;そして子ノードの数が現在のノードの兄弟ノードでk-子より少ないかどうかを調べます
    • 上記の操作を繰り返します
  • 子ノードの数が子>=kの場合

    • 回答は、現在のノードまたは現在のノードの子ノードに存在する必要があります
    • 子ノードの子ノードの数とk-1の関係を再帰的に求めます
    • 上記の操作を繰り返します

    上記のアイデアに従って、次のようにコードを編集します。

    完全なコード

var findKthNumber = function (n, k) {
  let count = 1;
  k--;
  while (k > 0) {
    const children = getChildren(count);
    if (children <= k) {
      k -= children;
      count++;
    } else {
      count = count * 10;
      k--;
    }
  }
  return count;
  function getChildren(c) {
    let child = 0;
    let left = c;
    let right = c;
    while (left <= n) {
      child += Math.min(right, n) - left + 1;
      left *= 10;
      right = right * 10 + 9;
    }
    return child;
  }
};
复制代码

エピローグ

著者のレベルは限られています。欠点がある場合は、私を訂正してください。コメントや提案は、コメント領域で閲覧して議論することを歓迎します。

おすすめ

転載: juejin.im/post/7078246470914146312