# Q4. Find Nth Smallest Integer with K One Bits **練習日期:** 2026-01-25 **類型:** Weekly Contest 486 ## 📘 題目敘述 給你兩個正整數 `n` 和 `k`。 請回傳「二進位表示中 **恰好有 `k` 個 1**」的正整數裡,第 `n` 小的那一個。 題目保證答案 **嚴格小於 `2^50`**。 ### 條件限制 * `1 <= n <= 250` * `1 <= k <= 50` * 答案嚴格小於 `2^50` ## 🧠 解題思路(最後TLE) 我的想法是: 我先用一個 `bin`(bool 陣列)表示「目前這個數的二進位哪些位元是 1」,並且從最小的開始(也就是最低位連續放 `k` 個 1:`111...000`)。 接著我要做的事情就是重複 `n-1` 次: **把目前的 bitmask 變成「下一個更大的、但 1 的數量仍然是 k」的 bitmask**。 這其實是在做「固定 1 的個數的下一個組合(next combination)」。 ### 所有變數 * `n, k`:題目輸入,要找第 `n` 小、且有 `k` 個 1 的正整數 * `bin`:`vector<bool>`,`bin[t] = true` 代表第 `t` 個 bit 是 1(我用 `t=0` 當最低位) * `pos`:目前最高的 1 出現到哪個 bit(用來最後把 `bin` 轉回數字時的最高位) * `ans`:最後要回傳的整數 * `orot / nrot`(這題沒有) * `count`:掃描過程中,累計「目前遇到的 1 的數量」(用來把低位重新塞回去) * `i, j, l`:迴圈索引用 ## 🪜 主要流程步驟 ### 1) 初始化成「最小的那個」 * 最小的數一定是:最低位開始連續放 `k` 個 1 例如 `k=3` → `0b111` 所以我先做: * `bin[0..k-1] = true` * 其餘都是 `false` --- ### 2) 重複做 `n-1` 次:產生下一個 bitmask(核心) 我在每一次迭代裡,從低位往高位掃描,找「可以往左移動的一顆 1」: #### 我在找的關鍵形狀 * 找到某個位置 `j` 滿足: * `bin[j] == 1` * `bin[j+1] == 0` 這代表這顆 1 可以「往更高位推一格」,讓整體數值變大,但仍保留 k 個 1。 #### 做法分兩步 **(A) 把這顆 1 往左推** * `bin[j] = 0` * `bin[j+1] = 1` * 同時更新 `pos = max(pos, j+1)`(因為最高位可能變大了) **(B) 把 `j` 左邊的低位重新整理成「最小」** * 我會用 `count` 記錄我一路走來遇到多少個 1(包含要搬的那顆之前累積的) * 當找到可搬動位置後,我就把 `0..j-1` 的 bit 重新排成: * 從最低位開始塞回 `count` 顆 1 * 其餘補 0 這樣可以確保: 在「固定高位變大的前提下」,低位保持最小,才能得到「下一個最小的合法數」。 --- ### 3) 把 `bin` 轉回整數 最後我從 `pos`(最高位)一路往 `0` 組回去: * 每一位做:`ans = ans * 2 + (bin[l] ? 1 : 0)` ## 💻 程式碼實作 ```cpp class Solution { public: long long nthSmallest(long long n, int k) { long long int ans = 0; int pos = k - 1; vector<bool> bin(51, false); for (int i = 0; i < k; i++) { bin[i] = true; } for (long long int i = 1; i < n; i++) { int count = 0; for (int j = 0; j < 50; j++) { if (bin[j] && !bin[j + 1]) { bin[j + 1] = true; bin[j] = false; pos = (pos > j + 1) ? pos : (j + 1); for (int k = 0; k < j; k++) { if (count > 0) { bin[k] = true; count--; } else { bin[k] = false; } } break; } else if (bin[j]) { count++; } } } for (int l = pos; l >= 0; l--) { ans = ans * 2 + (bin[l] ? 1 : 0); } return ans; } }; ``` ## 🔗 題目連結 https://leetcode.com/contest/weekly-contest-486/problems/find-nth-smallest-integer-with-k-one-bits/description/