08頭條實習生面試_字典序的第K小數字
阿新 • • 發佈:2018-11-23
LeetCode(440)
字典序的第K小數字
思路:
其實這是一個"十叉樹",如下圖:
1)每個節點的子節點可以有十個,比如節點1的子節點可以是10~19、節點2的位元組的可以是20~29、。。。
但是由於n大小的限制,構成的並不是一個"滿十叉樹"。
2)分析題目中給的例子可以知道,數字1的子節點有4個(10,11,12,13),而後面的數字2到9都沒有子節點,
那麼這道題實際上就變成了一個先序遍歷十叉樹的問題。
3)那麼,難點就變成了 計算出同一層兩個相鄰的節點的子節點的個數,也就是程式碼中的steps
3.1)當前節點為 curr (從curr = 1 開始),則同一層的下一個節點為 curr+1;
3.2)計算節點 curr到節點curr+1之間的子節點個數steps
3.2.1)如果子節點個數 大於 k,說明第k小的樹一定在子節點中,
繼續向下一層尋找:curr *=10;
k -= 1;(原因:向下一層尋找,肯定要減少前面的父節點,即 在上一層中的第k個數,在下一層中是第k-1個數)
3.2.2)如果子節點個數 小於或者等於 k,說明第k小的樹不在子節點中,
繼續向同一層下一個節點尋找:curr +=1;
k -= steps;(原因:向下一層尋找,肯定要減少前面的所有的位元組點)
以此類推,直到k為0推出迴圈,此時cur即為所求。
原始碼如下:
package Practise; import java.util.Scanner; public class Main8 { public static int findKthNumber(int n, int k) { int curr = 1; k = k - 1; while (k > 0) { long steps = 0, first = curr, last = curr + 1; while (first <= n) { steps += Math.min((long)n + 1, last) - first; first *= 10; last *= 10; } if (steps <= k) { curr += 1; k -= steps; } else { curr *= 10; k -= 1; } } return curr; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int k = sc.nextInt(); System.out.println(findKthNumber(n,k)); } }