2525<pre >
2626<strong >输入:</strong > n = 5
2727<strong >输出:</strong > 5
28- <strong >解释:</strong >
28+ <strong >解释:</strong >
2929下面列出范围在 [0, 5] 的非负整数与其对应的二进制表示:
30300 : 0
31311 : 1
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
107111class 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 == 1 and 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
128131class 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 {
163168class Solution {
164169public:
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
198202func 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
235239function 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