
2026-05-29:二进制中恰好K个1的第N小整数。用go语言,给定两个正整数 n 和 k,要求你找到这样一个数:在它的二进制表示中,恰好有 k 个比特位为 1。把所有满足条件的正整数按大小从小到大排序,返回其中第 n 个数。题目保证这个答案一定小于 2⁵⁰。
1 <= n <= 2⁵⁰。
1 <= k <= 50。
答案严格小于 2⁵⁰。
输入: n = 4, k = 2。
输出: 9。
解释:
二进制表示中恰好包含 k = 2 个 1 的前 4 个正整数分别是:
3 = 11₂。
5 = 101₂。
6 = 110₂。
9 = 1001₂。
题目来自力扣3821。
这是算法的初始化步骤,在程序启动时自动执行,核心作用是提前计算好所有需要用到的组合数,为后续快速判断做准备。
C(i, j) 表示从 i 个位置中选 j 个位置放1 的总方案数,这正好对应「二进制数有j个1」的数量。C(i,j) = C(i-1,j-1) + C(i-1,j)(选当前位为1 + 选当前位为0)。算法的核心思想:从最高位(第49位)到最低位(第0位),一位一位确定当前二进制位是0还是1,最终拼出第n小的数。
我们的目标:找二进制恰好2个1、从小到大排序后的第4个数。 已知满足条件的数排序:3(11)、5(101)、6(110)、9(1001)。
这些位的位置非常高,我们计算:如果当前位填0,剩余位置能填出多少个「恰好2个1」的数。
公式:C(剩余位数, 剩余1的个数)
计算发现:这些高位填0时,能生成的方案数远大于4。 这意味着:第4个数一定不包含这些高位,所以所有高位全部填0。
C(3,2)=3;C(2,1)=2;C(1,1)=1;最终构造的数是 9,与题目示例输出一致。
分为两部分:
mx 是固定常数50,因此总时间复杂度为 O(1)(常数级时间)。
我们只开辟了一个固定大小的二维数组 comb[mx][mx+1] 存储组合数,mx=50 是固定常数,没有其他动态开辟的空间。
因此总额外空间复杂度为 O(1)(常数级空间)。
.
package main
import (
"fmt"
)
const mx = 50
var comb [mx][mx + 1]int64
func init() {
// 预处理组合数
for i := range comb {
comb[i][0] = 1
for j := 1; j <= i; j++ {
comb[i][j] = comb[i-1][j-1] + comb[i-1][j]
}
}
}
func nthSmallest(n int64, k int) (ans int64) {
for i := mx - 1; k > 0; i-- {
c := comb[i][k] // 第 i 位填 0 的方案数
if n > c { // n 比较大,第 i 位必须填 1
n -= c
ans |= 1 << i
k-- // 维护剩余的 1 的个数
}
}
return
}
func main() {
n := int64(4)
k := 2
result := nthSmallest(n, k)
fmt.Println(result)
}

.
# -*-coding:utf-8-*-
mx = 50
# 预处理组合数
comb = [[0] * (mx + 1) for _ in range(mx)]
for i in range(mx):
comb[i][0] = 1
for j in range(1, i + 1):
comb[i][j] = comb[i-1][j-1] + comb[i-1][j]
def nth_smallest(n: int, k: int) -> int:
"""
找到第 n 个恰好包含 k 个 1 的二进制数(从小到大)
返回对应的整数值
"""
ans = 0
i = mx - 1
while k > 0 and i >= 0:
c = comb[i][k] # 第 i 位填 0 的方案数
if n > c: # n 比较大,第 i 位必须填 1
n -= c
ans |= 1 << i
k -= 1 # 维护剩余的 1 的个数
i -= 1
return ans
if __name__ == "__main__":
n = 4
k = 2
result = nth_smallest(n, k)
print(result)
.
#include <iostream>
#include <cstdint>
constint mx = 50;
int64_t comb[mx][mx + 1];
void init_comb() {
for (int i = 0; i < mx; ++i) {
comb[i][0] = 1;
for (int j = 1; j <= i; ++j) {
comb[i][j] = comb[i - 1][j - 1] + comb[i - 1][j];
}
}
}
int64_t nthSmallest(int64_t n, int k) {
int64_t ans = 0;
for (int i = mx - 1; k > 0; --i) {
int64_t c = comb[i][k]; // 在第 i 位填 0 的方案数
if (n > c) { // n 比较大,第 i 位必须填 1
n -= c;
ans |= (1LL << i);
--k; // 剩余 1 的个数减 1
}
}
return ans;
}
int main() {
init_comb();
int64_t n = 4;
int k = 2;
int64_t result = nthSmallest(n, k);
std::cout << result << std::endl;
return0;
}

·
我们相信人工智能为普通人提供了一种“增强工具”,并致力于分享全方位的AI知识。在这里,您可以找到最新的AI科普文章、工具评测、提升效率的秘籍以及行业洞察。 欢迎关注“福大大架构师每日一题”,发消息可获得面试资料,让AI助力您的未来发展。
·