Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,32 +74,168 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3800-3899/3821.Fi

<!-- solution:start -->

### 方法一
### 方法一:组合数学 + 贪心

我们需要找到第 $n$ 个二进制表示中恰好包含 $k$ 个 $1$ 的正整数。我们可以从高位到低位依次确定每一位是 $0$ 还是 $1$。

假设当前处理的是第 $i$ 位(从 $49$ 开始到 $0$),如果我们将该位设置为 $0$,那么剩下的 $k$ 个 $1$ 需要从低 $i$ 位中选择,可能的组合数为 $C(i, k)$。如果 $n$ 大于 $C(i, k)$,说明第 $n$ 个数的第 $i$ 位必须是 $1$,我们将该位设置为 $1$,并将 $n$ 减去 $C(i, k)$,同时将 $k$ 减 $1$(因为我们已经使用了一个 $1$)。否则,我们将该位设置为 $0$。

我们重复上述过程,直到处理完所有位或者 $k$ 减为 $0$。

时间复杂度 $(\log^2 M)$,空间复杂度 $O(\log^2 M)$,其中 $M$ 是答案的上限 $2^{50}$。

<!-- tabs:start -->

#### Python3

```python

mx = 50
c = [[0] * (mx + 1) for _ in range(mx)]
for i in range(mx):
c[i][0] = 1
for j in range(1, i + 1):
c[i][j] = c[i - 1][j - 1] + c[i - 1][j]


class Solution:
def nthSmallest(self, n: int, k: int) -> int:
ans = 0
for i in range(49, -1, -1):
if n > c[i][k]:
n -= c[i][k]
ans |= 1 << i
k -= 1
if k == 0:
break
return ans
```

#### Java

```java

class Solution {
private static final int MX = 50;
private static final long[][] c = new long[MX][MX + 1];

static {
for (int i = 0; i < MX; i++) {
c[i][0] = 1;
for (int j = 1; j <= i; j++) {
c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
}
}
}

public long nthSmallest(long n, int k) {
long ans = 0;
for (int i = 49; i >= 0; i--) {
if (n > c[i][k]) {
n -= c[i][k];
ans |= 1L << i;
k--;
if (k == 0) {
break;
}
}
}
return ans;
}
}
```

#### C++

```cpp

constexpr int MX = 50;
long long c[MX][MX + 1];

auto init = [] {
for (int i = 0; i < MX; i++) {
c[i][0] = 1;
for (int j = 1; j <= i; j++) {
c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
}
}
return 0;
}();

class Solution {
public:
long long nthSmallest(long long n, int k) {
long long ans = 0;
for (int i = 49; i >= 0; i--) {
if (n > c[i][k]) {
n -= c[i][k];
ans |= 1LL << i;
if (--k == 0) {
break;
}
}
}
return ans;
}
};
```

#### Go

```go
const MX = 50

var c [MX][MX + 1]int64

func init() {
for i := 0; i < MX; i++ {
c[i][0] = 1
for j := 1; j <= i; j++ {
c[i][j] = c[i-1][j-1] + c[i-1][j]
}
}
}

func nthSmallest(n int64, k int) int64 {
var ans int64 = 0
for i := 49; i >= 0; i-- {
if n > c[i][k] {
n -= c[i][k]
ans |= 1 << i
k--
if k == 0 {
break
}
}
}
return ans
}
```

#### TypeScript

```ts
const MX = 50;
const c: bigint[][] = Array.from({ length: MX }, () => Array(MX + 1).fill(0n));

for (let i = 0; i < MX; i++) {
c[i][0] = 1n;
for (let j = 1; j <= i; j++) {
c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
}
}

function nthSmallest(n: number, k: number): number {
let nn = BigInt(n);
let ans = 0n;
for (let i = 49; i >= 0; i--) {
if (nn > c[i][k]) {
nn -= c[i][k];
ans |= 1n << BigInt(i);
if (--k === 0) {
break;
}
}
}
return Number(ans);
}
```

<!-- tabs:end -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,32 +72,168 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3800-3899/3821.Fi

<!-- solution:start -->

### Solution 1
### Solution 1: Combinatorics + Greedy

We need to find the $n$-th smallest positive integer that contains exactly $k$ ones in its binary representation. We can determine each bit from the most significant to the least significant, deciding whether it is $0$ or $1$.

Suppose we are currently processing the $i$-th bit (from $49$ down to $0$). If we set this bit to $0$, then the remaining $k$ ones need to be chosen from the lower $i$ bits, and the number of possible combinations is $C(i, k)$. If $n$ is greater than $C(i, k)$, it implies that the $i$-th bit of the $n$-th number must be $1$. In this case, we set this bit to $1$, subtract $C(i, k)$ from $n$, and decrement $k$ by $1$ (since we have already used one $1$). Otherwise, we set this bit to $0$.

We repeat the above process until all bits are processed or $k$ becomes $0$.

The time complexity is $O(\log^2 M)$, and the space complexity is $O(\log^2 M)$, where $M$ is the upper bound of the answer, $2^{50}$.

<!-- tabs:start -->

#### Python3

```python

mx = 50
c = [[0] * (mx + 1) for _ in range(mx)]
for i in range(mx):
c[i][0] = 1
for j in range(1, i + 1):
c[i][j] = c[i - 1][j - 1] + c[i - 1][j]


class Solution:
def nthSmallest(self, n: int, k: int) -> int:
ans = 0
for i in range(49, -1, -1):
if n > c[i][k]:
n -= c[i][k]
ans |= 1 << i
k -= 1
if k == 0:
break
return ans
```

#### Java

```java

class Solution {
private static final int MX = 50;
private static final long[][] c = new long[MX][MX + 1];

static {
for (int i = 0; i < MX; i++) {
c[i][0] = 1;
for (int j = 1; j <= i; j++) {
c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
}
}
}

public long nthSmallest(long n, int k) {
long ans = 0;
for (int i = 49; i >= 0; i--) {
if (n > c[i][k]) {
n -= c[i][k];
ans |= 1L << i;
k--;
if (k == 0) {
break;
}
}
}
return ans;
}
}
```

#### C++

```cpp

constexpr int MX = 50;
long long c[MX][MX + 1];

auto init = [] {
for (int i = 0; i < MX; i++) {
c[i][0] = 1;
for (int j = 1; j <= i; j++) {
c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
}
}
return 0;
}();

class Solution {
public:
long long nthSmallest(long long n, int k) {
long long ans = 0;
for (int i = 49; i >= 0; i--) {
if (n > c[i][k]) {
n -= c[i][k];
ans |= 1LL << i;
if (--k == 0) {
break;
}
}
}
return ans;
}
};
```

#### Go

```go
const MX = 50

var c [MX][MX + 1]int64

func init() {
for i := 0; i < MX; i++ {
c[i][0] = 1
for j := 1; j <= i; j++ {
c[i][j] = c[i-1][j-1] + c[i-1][j]
}
}
}

func nthSmallest(n int64, k int) int64 {
var ans int64 = 0
for i := 49; i >= 0; i-- {
if n > c[i][k] {
n -= c[i][k]
ans |= 1 << i
k--
if k == 0 {
break
}
}
}
return ans
}
```

#### TypeScript

```ts
const MX = 50;
const c: bigint[][] = Array.from({ length: MX }, () => Array(MX + 1).fill(0n));

for (let i = 0; i < MX; i++) {
c[i][0] = 1n;
for (let j = 1; j <= i; j++) {
c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
}
}

function nthSmallest(n: number, k: number): number {
let nn = BigInt(n);
let ans = 0n;
for (let i = 49; i >= 0; i--) {
if (nn > c[i][k]) {
nn -= c[i][k];
ans |= 1n << BigInt(i);
if (--k === 0) {
break;
}
}
}
return Number(ans);
}
```

<!-- tabs:end -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
constexpr int MX = 50;
long long c[MX][MX + 1];

auto init = [] {
for (int i = 0; i < MX; i++) {
c[i][0] = 1;
for (int j = 1; j <= i; j++) {
c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
}
}
return 0;
}();

class Solution {
public:
long long nthSmallest(long long n, int k) {
long long ans = 0;
for (int i = 49; i >= 0; i--) {
if (n > c[i][k]) {
n -= c[i][k];
ans |= 1LL << i;
if (--k == 0) {
break;
}
}
}
return ans;
}
};
Loading
Loading