Skip to content

Commit 2e984af

Browse files
committed
feat: add solutions to lc problem: No.0600
No.0600.Non-negative Integers without Consecutive Ones
1 parent 7ab6a88 commit 2e984af

File tree

6 files changed

+445
-2
lines changed

6 files changed

+445
-2
lines changed

solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README.md

+172-1
Original file line numberDiff line numberDiff line change
@@ -51,22 +51,193 @@
5151

5252
<!-- 这里可写通用的实现逻辑 -->
5353

54+
**方法一:数位 DP**
55+
56+
这道题实际上是求在给定区间 $[l,..r]$ 中,数字的二进制表示不包含连续的 $1$ 的个数。个数与数的位数以及每个二进制位上的数字有关。我们可以用数位 DP 的思路来解决这道题。数位 DP 中,数的大小对复杂度的影响很小。
57+
58+
对于区间 $[l,..r]$ 问题,我们一般会将其转化为 $[1,..r]$ 然后再减去 $[1,..l - 1]$ 的问题,即:
59+
60+
$$
61+
ans = \sum_{i=1}^{r} ans_i - \sum_{i=1}^{l-1} ans_i
62+
$$
63+
64+
不过对于本题而言,我们只需要求出区间 $[0,..r]$ 的值即可。
65+
66+
这里我们用记忆化搜索来实现数位 DP。从起点向下搜索,到最底层得到方案数,一层层向上返回答案并累加,最后从搜索起点得到最终的答案。
67+
68+
基本步骤如下:
69+
70+
1. 将数字 $n$ 转为二进制数组 $a$,其中 $a[1]$ 为最低位,而 $a[len]$ 为最高位;
71+
1. 根据题目信息,设计函数 $dfs()$,对于本题,我们定义 $dfs(pos, pre, limit)$,答案为 $dfs(len, 1, true)$。
72+
73+
其中:
74+
75+
- `pos` 表示数字的位数,从末位或者第一位开始,一般根据题目的数字构造性质来选择顺序。对于本题,我们选择从高位开始,因此,`pos` 的初始值为 `len`
76+
- `pre` 表示当前数字二进制位上的数字,对于本题,`pre` 的初始值为 `1`
77+
- `limit` 表示可填的数字的限制,如果无限制,那么可以选择 $[0,1]$,否则,只能选择 $[0,..a[pos]]$。如果 `limit``true` 且已经取到了能取到的最大值,那么下一个 `limit` 同样为 `true`;如果 `limit``true` 但是还没有取到最大值,或者 `limit``false`,那么下一个 `limit``false`
78+
79+
关于函数的实现细节,可以参考下面的代码。
80+
81+
时间复杂度 $O(\log n)$。
82+
83+
相似题目:[233. 数字 1 的个数](/solution/0200-0299/0233.Number%20of%20Digit%20One/README.md)
84+
5485
<!-- tabs:start -->
5586

5687
### **Python3**
5788

5889
<!-- 这里可写当前语言的特殊实现逻辑 -->
5990

6091
```python
61-
92+
class Solution:
93+
def findIntegers(self, n: int) -> int:
94+
@cache
95+
def dfs(pos, pre, limit):
96+
if pos <= 0:
97+
return 1
98+
up = a[pos] if limit else 1
99+
ans = 0
100+
for i in range(up + 1):
101+
if pre == 1 and i == 1:
102+
continue
103+
ans += dfs(pos - 1, i, limit and i == up)
104+
return ans
105+
106+
a = [0] * 33
107+
l = 1
108+
while n:
109+
a[l] = n & 1
110+
n >>= 1
111+
l += 1
112+
return dfs(l, 1, True)
62113
```
63114

64115
### **Java**
65116

66117
<!-- 这里可写当前语言的特殊实现逻辑 -->
67118

68119
```java
120+
class Solution {
121+
private int[] a = new int[33];
122+
private int[][] dp = new int[33][2];
123+
124+
public int findIntegers(int n) {
125+
int len = 1;
126+
while (n > 0) {
127+
a[len++] = n & 1;
128+
n >>= 1;
129+
}
130+
for (var e : dp) {
131+
Arrays.fill(e, -1);
132+
}
133+
return dfs(len, 1, true);
134+
}
135+
136+
private int dfs(int pos, int pre, boolean limit) {
137+
if (pos <= 0) {
138+
return 1;
139+
}
140+
if (!limit && dp[pos][pre] != -1) {
141+
return dp[pos][pre];
142+
}
143+
int up = limit ? a[pos] : 1;
144+
int ans = 0;
145+
for (int i = 0; i <= up; ++i) {
146+
if (!(pre == 1 && i == 1)) {
147+
ans += dfs(pos - 1, i, limit && i == up);
148+
}
149+
}
150+
if (!limit) {
151+
dp[pos][pre] = ans;
152+
}
153+
return ans;
154+
}
155+
}
156+
```
157+
158+
### **C++**
159+
160+
```cpp
161+
class Solution {
162+
public:
163+
int a[33];
164+
int dp[33][2];
165+
166+
int findIntegers(int n) {
167+
int len = 1;
168+
while (n) {
169+
a[len++] = n & 1;
170+
n >>= 1;
171+
}
172+
memset(dp, -1, sizeof dp);
173+
return dfs(len, 1, true);
174+
}
175+
176+
int dfs(int pos, int pre, bool limit) {
177+
if (pos <= 0) {
178+
return 1;
179+
}
180+
if (!limit && dp[pos][pre] != -1) {
181+
return dp[pos][pre];
182+
}
183+
int ans = 0;
184+
int up = limit ? a[pos] : 1;
185+
for (int i = 0; i <= up; ++i) {
186+
if (!(pre == 1 && i == 1)) {
187+
ans += dfs(pos - 1, i, limit && i == up);
188+
}
189+
}
190+
if (!limit) {
191+
dp[pos][pre] = ans;
192+
}
193+
return ans;
194+
}
195+
};
196+
```
69197
198+
### **Go**
199+
200+
```go
201+
func findIntegers(n int) int {
202+
a := make([]int, 33)
203+
dp := make([][]int, 33)
204+
for i := range dp {
205+
dp[i] = make([]int, 2)
206+
for j := range dp[i] {
207+
dp[i][j] = -1
208+
}
209+
}
210+
l := 1
211+
for n > 0 {
212+
a[l] = n & 1
213+
n >>= 1
214+
l++
215+
}
216+
var dfs func(int, int, bool) int
217+
dfs = func(pos, pre int, limit bool) int {
218+
if pos <= 0 {
219+
return 1
220+
}
221+
if !limit && dp[pos][pre] != -1 {
222+
return dp[pos][pre]
223+
}
224+
up := 1
225+
if limit {
226+
up = a[pos]
227+
}
228+
ans := 0
229+
for i := 0; i <= up; i++ {
230+
if !(pre == 1 && i == 1) {
231+
ans += dfs(pos-1, i, limit && i == up)
232+
}
233+
}
234+
if !limit {
235+
dp[pos][pre] = ans
236+
}
237+
return ans
238+
}
239+
return dfs(l, 1, true)
240+
}
70241
```
71242

72243
### **...**

solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README_EN.md

+141-1
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,153 @@ Among them, only integer 3 disobeys the rule (two consecutive ones) and the othe
5151
### **Python3**
5252

5353
```python
54-
54+
class Solution:
55+
def findIntegers(self, n: int) -> int:
56+
@cache
57+
def dfs(pos, pre, limit):
58+
if pos <= 0:
59+
return 1
60+
up = a[pos] if limit else 1
61+
ans = 0
62+
for i in range(up + 1):
63+
if pre == 1 and i == 1:
64+
continue
65+
ans += dfs(pos - 1, i, limit and i == up)
66+
return ans
67+
68+
a = [0] * 33
69+
l = 1
70+
while n:
71+
a[l] = n & 1
72+
n >>= 1
73+
l += 1
74+
return dfs(l, 1, True)
5575
```
5676

5777
### **Java**
5878

5979
```java
80+
class Solution {
81+
private int[] a = new int[33];
82+
private int[][] dp = new int[33][2];
83+
84+
public int findIntegers(int n) {
85+
int len = 1;
86+
while (n > 0) {
87+
a[len++] = n & 1;
88+
n >>= 1;
89+
}
90+
for (var e : dp) {
91+
Arrays.fill(e, -1);
92+
}
93+
return dfs(len, 1, true);
94+
}
95+
96+
private int dfs(int pos, int pre, boolean limit) {
97+
if (pos <= 0) {
98+
return 1;
99+
}
100+
if (!limit && dp[pos][pre] != -1) {
101+
return dp[pos][pre];
102+
}
103+
int up = limit ? a[pos] : 1;
104+
int ans = 0;
105+
for (int i = 0; i <= up; ++i) {
106+
if (!(pre == 1 && i == 1)) {
107+
ans += dfs(pos - 1, i, limit && i == up);
108+
}
109+
}
110+
if (!limit) {
111+
dp[pos][pre] = ans;
112+
}
113+
return ans;
114+
}
115+
}
116+
```
117+
118+
### **C++**
119+
120+
```cpp
121+
class Solution {
122+
public:
123+
int a[33];
124+
int dp[33][2];
125+
126+
int findIntegers(int n) {
127+
int len = 1;
128+
while (n) {
129+
a[len++] = n & 1;
130+
n >>= 1;
131+
}
132+
memset(dp, -1, sizeof dp);
133+
return dfs(len, 1, true);
134+
}
135+
136+
int dfs(int pos, int pre, bool limit) {
137+
if (pos <= 0) {
138+
return 1;
139+
}
140+
if (!limit && dp[pos][pre] != -1) {
141+
return dp[pos][pre];
142+
}
143+
int ans = 0;
144+
int up = limit ? a[pos] : 1;
145+
for (int i = 0; i <= up; ++i) {
146+
if (!(pre == 1 && i == 1)) {
147+
ans += dfs(pos - 1, i, limit && i == up);
148+
}
149+
}
150+
if (!limit) {
151+
dp[pos][pre] = ans;
152+
}
153+
return ans;
154+
}
155+
};
156+
```
60157
158+
### **Go**
159+
160+
```go
161+
func findIntegers(n int) int {
162+
a := make([]int, 33)
163+
dp := make([][]int, 33)
164+
for i := range dp {
165+
dp[i] = make([]int, 2)
166+
for j := range dp[i] {
167+
dp[i][j] = -1
168+
}
169+
}
170+
l := 1
171+
for n > 0 {
172+
a[l] = n & 1
173+
n >>= 1
174+
l++
175+
}
176+
var dfs func(int, int, bool) int
177+
dfs = func(pos, pre int, limit bool) int {
178+
if pos <= 0 {
179+
return 1
180+
}
181+
if !limit && dp[pos][pre] != -1 {
182+
return dp[pos][pre]
183+
}
184+
up := 1
185+
if limit {
186+
up = a[pos]
187+
}
188+
ans := 0
189+
for i := 0; i <= up; i++ {
190+
if !(pre == 1 && i == 1) {
191+
ans += dfs(pos-1, i, limit && i == up)
192+
}
193+
}
194+
if !limit {
195+
dp[pos][pre] = ans
196+
}
197+
return ans
198+
}
199+
return dfs(l, 1, true)
200+
}
61201
```
62202

63203
### **...**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
class Solution {
2+
public:
3+
int a[33];
4+
int dp[33][2];
5+
6+
int findIntegers(int n) {
7+
int len = 1;
8+
while (n) {
9+
a[len++] = n & 1;
10+
n >>= 1;
11+
}
12+
memset(dp, -1, sizeof dp);
13+
return dfs(len, 1, true);
14+
}
15+
16+
int dfs(int pos, int pre, bool limit) {
17+
if (pos <= 0) {
18+
return 1;
19+
}
20+
if (!limit && dp[pos][pre] != -1) {
21+
return dp[pos][pre];
22+
}
23+
int ans = 0;
24+
int up = limit ? a[pos] : 1;
25+
for (int i = 0; i <= up; ++i) {
26+
if (!(pre == 1 && i == 1)) {
27+
ans += dfs(pos - 1, i, limit && i == up);
28+
}
29+
}
30+
if (!limit) {
31+
dp[pos][pre] = ans;
32+
}
33+
return ans;
34+
}
35+
};

0 commit comments

Comments
 (0)