Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f388d35

Browse files
feat: update solutions to lc problem: No.0600 (doocs#3541)
No.0600.Non-negative Integers without Consecutive Ones
1 parent 9492cca commit f388d35

File tree

7 files changed

+219
-217
lines changed

7 files changed

+219
-217
lines changed

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

Lines changed: 76 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ tags:
2525
<pre>
2626
<strong>输入:</strong> n = 5
2727
<strong>输出:</strong> 5
28-
<strong>解释:</strong>
28+
<strong>解释:</strong>
2929
下面列出范围在 [0, 5] 的非负整数与其对应的二进制表示:
3030
0 : 0
3131
1 : 1
@@ -77,18 +77,22 @@ $$
7777

7878
这里我们用记忆化搜索来实现数位 DP。基本步骤如下:
7979

80-
1. 将数字 $n$ 转为二进制字符串 $s$;
81-
1. 根据题目信息,设计函数 $\textit{dfs}(),ドル对于本题,我们定义 $\textit{dfs}(\textit{pos}, \textit{pre}, \textit{limit}),ドル答案为 $\textit{dfs}(\textit{0}, 0, \textit{true})$。
80+
我们首先获取数字 $n$ 的二进制长度,记为 $m$。然后根据题目信息,我们设计函数 $\textit{dfs}(i, \textit{pre}, \textit{limit}),ドル其中:
8281

83-
其中:
82+
- 数字 $i$ 表示当前搜索到的位置,我们从数字的最高位开始搜索,即二进制字符串的首字符;
83+
- 数字 $\textit{pre}$ 表示上一个数字二进制位上的数字,对于本题,$\textit{pre}$ 的初始值为 0ドル$;
84+
- 布尔值 $\textit{limit}$ 表示可填的数字的限制,如果无限制,那么可以选择 $[0,1],ドル否则,只能选择 $[0, \textit{up}]$。
8485

85-
- `pos` 表示数字的位数,我们从数字的最高位开始,即二进制字符串的首字符;
86-
- `pre` 表示当前数字二进制位上的数字,对于本题,`pre` 的初始值为 `0`;
87-
- `limit` 表示可填的数字的限制,如果无限制,那么可以选择 $[0,1],ドル否则,只能选择 $[0,..s[\textit{pos}]]$。
86+
函数的执行过程如下:
8887

89-
关于函数的实现细节,可以参考下面的代码。
88+
如果 $i$ 超过了数字 $n$ 的长度,即 $i \lt 0,ドル说明搜索结束,直接返回 1ドル$。否则,我们从 0ドル$ 到 $\textit{up}$ 枚举位置 $i$ 的数字 $j,ドル对于每一个 $j$:
9089

91-
时间复杂度 $O(\log n),ドル空间复杂度 $O(\log n)$。其中 $n$ 为题目给定的数字。
90+
- 如果 $\textit{pre}$ 和 $j$ 都为 1ドル,ドル说明有连续的 1ドル,ドル直接跳过;
91+
- 否则,我们递归到下一层,更新 $\textit{pre}$ 为 $j,ドル并将 $\textit{limit}$ 更新为 $\textit{limit}$ 与 $j$ 是否等于 $\textit{up}$ 的逻辑与。
92+
93+
最后,我们将所有递归到下一层的结果累加,即为答案。
94+
95+
时间复杂度 $O(\log n),ドル空间复杂度 $O(\log n)$。其中 $n$ 为题目给定的正整数。
9296

9397
相似题目:
9498

@@ -107,50 +111,51 @@ $$
107111
class Solution:
108112
def findIntegers(self, n: int) -> int:
109113
@cache
110-
def dfs(pos: int, pre: int, limit: bool) -> int:
111-
if pos ==len(s):
114+
def dfs(i: int, pre: int, limit: bool) -> int:
115+
if i <0:
112116
return 1
113-
up = int(s[pos]) if limit else 1
117+
up = (n >> i &1) if limit else 1
114118
ans = 0
115-
for i in range(up + 1):
116-
if pre ==1and i ==1:
119+
for j in range(up + 1):
120+
if pre and j:
117121
continue
118-
ans += dfs(pos + 1, i, limit and i == up)
122+
ans += dfs(i - 1, j, limit and j == up)
119123
return ans
120124

121-
s = bin(n)[2:]
122-
return dfs(0, 0, True)
125+
return dfs(n.bit_length() - 1, 0, True)
123126
```
124127

125128
#### Java
126129

127130
```java
128131
class Solution {
129-
private char[] s;
132+
private int n;
130133
private Integer[][] f;
131134

132135
public int findIntegers(int n) {
133-
s = Integer.toBinaryString(n).toCharArray();
134-
f = new Integer[s.length][2];
135-
return dfs(0, 0, true);
136+
this.n = n;
137+
int m = Integer.SIZE - Integer.numberOfLeadingZeros(n);
138+
f = new Integer[m][2];
139+
return dfs(m - 1, 0, true);
136140
}
137141

138-
private int dfs(int pos, int pre, boolean limit) {
139-
if (pos >= s.length) {
142+
private int dfs(int i, int pre, boolean limit) {
143+
if (i <0) {
140144
return 1;
141145
}
142-
if (!limit && f[pos][pre] != null) {
143-
return f[pos][pre];
146+
if (!limit && f[i][pre] != null) {
147+
return f[i][pre];
144148
}
145-
int up = limit ? s[pos] -'0' : 1;
149+
int up = limit ? (n >> i &1) : 1;
146150
int ans = 0;
147-
for (int i = 0; i <= up; ++i) {
148-
if (!(pre == 1 && i == 1)) {
149-
ans += dfs(pos +1, i, limit && i == up);
151+
for (int j = 0; j <= up; ++j) {
152+
if (j == 1 && pre == 1) {
153+
continue;
150154
}
155+
ans += dfs(i - 1, j, limit && j == up);
151156
}
152157
if (!limit) {
153-
f[pos][pre] = ans;
158+
f[i][pre] = ans;
154159
}
155160
return ans;
156161
}
@@ -163,31 +168,30 @@ class Solution {
163168
class Solution {
164169
public:
165170
int findIntegers(int n) {
166-
string s = bitset<32>(n).to_string();
167-
s = s.substr(s.find('1'));
168-
int m = s.size();
171+
int m = 32 - __builtin_clz(n);
169172
int f[m][2];
170173
memset(f, -1, sizeof(f));
171-
auto dfs = [&](auto&& dfs, int pos, int pre, bool limit) -> int {
172-
if (pos >= m) {
174+
auto dfs = [&](auto&& dfs, int i, int pre, bool limit) -> int {
175+
if (i < 0) {
173176
return 1;
174177
}
175-
if (!limit && f[pos][pre] != -1) {
176-
return f[pos][pre];
178+
if (!limit && f[i][pre] != -1) {
179+
return f[i][pre];
177180
}
178-
int up = limit ? s[pos] - '0' : 1;
181+
int up = limit ? (n >> i & 1) : 1;
179182
int ans = 0;
180-
for (int i = 0; i <= up; ++i) {
181-
if (!(pre == 1 && i == 1)) {
182-
ans += dfs(dfs, pos + 1, i, limit && i == up);
183+
for (int j = 0; j <= up; ++j) {
184+
if (j && pre) {
185+
continue;
183186
}
187+
ans += dfs(dfs, i - 1, j, limit && j == up);
184188
}
185189
if (!limit) {
186-
f[pos][pre] = ans;
190+
f[i][pre] = ans;
187191
}
188192
return ans;
189193
};
190-
return dfs(dfs, 0, 0, true);
194+
return dfs(dfs, m - 1, 0, true);
191195
}
192196
};
193197
```
@@ -196,68 +200,66 @@ public:
196200
197201
```go
198202
func findIntegers(n int) int {
199-
s := strconv.FormatInt(int64(n), 2)
200-
m := len(s)
201-
f := make([][]int, m)
203+
m := bits.Len(uint(n))
204+
f := make([][2]int, m)
202205
for i := range f {
203-
f[i] = []int{-1, -1}
206+
f[i] = [2]int{-1, -1}
204207
}
205-
var dfs func(int, int, bool) int
206-
dfs = func(pos int, pre int, limit bool) int {
207-
if pos >= m {
208+
var dfs func(i, pre int, limit bool) int
209+
dfs = func(i, pre int, limit bool) int {
210+
if i < 0 {
208211
return 1
209212
}
210-
if !limit && f[pos][pre] != -1 {
211-
return f[pos][pre]
213+
if !limit && f[i][pre] != -1 {
214+
return f[i][pre]
212215
}
213216
up := 1
214217
if limit {
215-
up = int(s[pos] - '0')
218+
up = n >> i & 1
216219
}
217220
ans := 0
218-
for i := 0; i <= up; i++ {
219-
if !(pre == 1 && i == 1) {
220-
ans += dfs(pos+1, i, limit && i == up)
221+
for j := 0; j <= up; j++ {
222+
if j == 1 && pre == 1 {
223+
continue
221224
}
225+
ans += dfs(i-1, j, limit && j == up)
222226
}
223227
if !limit {
224-
f[pos][pre] = ans
228+
f[i][pre] = ans
225229
}
226230
return ans
227231
}
228-
return dfs(0, 0, true)
232+
return dfs(m-1, 0, true)
229233
}
230234
```
231235

232236
#### TypeScript
233237

234238
```ts
235239
function findIntegers(n: number): number {
236-
const s = n.toString(2);
237-
const m = s.length;
238-
const f: number[][] = Array.from({ length: m }, () => [-1, -1]);
239-
240-
function dfs(pos: number, pre: number, limit: boolean): number {
241-
if (pos >= m) {
240+
const m = n.toString(2).length;
241+
const f: number[][] = Array.from({ length: m }, () => Array(2).fill(-1));
242+
const dfs = (i: number, pre: number, limit: boolean): number => {
243+
if (i < 0) {
242244
return 1;
243245
}
244-
if (!limit && f[pos][pre] !== -1) {
245-
return f[pos][pre];
246+
if (!limit && f[i][pre] !== -1) {
247+
return f[i][pre];
246248
}
247-
const up = limit ? parseInt(s[pos]) : 1;
249+
const up = limit ? (n>>i) &1 : 1;
248250
let ans = 0;
249-
for (let i = 0; i <= up; ++i) {
250-
if (!(pre === 1 && i === 1)) {
251-
ans+=dfs(pos+1, i, limit&&i===up);
251+
for (let j = 0; j <= up; ++j) {
252+
if (pre === 1 && j === 1) {
253+
continue;
252254
}
255+
ans += dfs(i - 1, j, limit && j === up);
253256
}
254257
if (!limit) {
255-
f[pos][pre] = ans;
258+
f[i][pre] = ans;
256259
}
257260
return ans;
258-
}
259-
260-
return dfs(0, 0, true);
261+
};
262+
return dfs(m - 1, 0, true);
261263
}
262264
```
263265

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /