diff --git a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README.md b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README.md index e81e6281b6235..f5a7f75b54741 100644 --- a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README.md +++ b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README.md @@ -25,7 +25,7 @@ tags:
 输入: n = 5
 输出: 5
-解释: 
+解释:
 下面列出范围在 [0, 5] 的非负整数与其对应的二进制表示:
 0 : 0
 1 : 1
@@ -67,30 +67,28 @@ tags:
 
 这道题实际上是求在给定区间 $[l,..r]$ 中,数字的二进制表示不包含连续的 $1$ 的个数。个数与数的位数以及每个二进制位上的数字有关。我们可以用数位 DP 的思路来解决这道题。数位 DP 中,数的大小对复杂度的影响很小。
 
-对于区间 $[l,..r]$ 问题,我们一般会将其转化为 $[1,..r]$ 然后再减去 $[1,..l - 1]$ 的问题,即:
+对于区间 $[l,..r]$ 问题,我们一般会将其转化为 $[0,..r]$ 然后再减去 $[0,..l - 1]$ 的问题,即:
 
 $$
-ans = \sum_{i=1}^{r} ans_i -  \sum_{i=1}^{l-1} ans_i
+ans = \sum_{i=0}^{r} ans_i -  \sum_{i=0}^{l-1} ans_i
 $$
 
 不过对于本题而言,我们只需要求出区间 $[0,..r]$ 的值即可。
 
-这里我们用记忆化搜索来实现数位 DP。从起点向下搜索,到最底层得到方案数,一层层向上返回答案并累加,最后从搜索起点得到最终的答案。
+这里我们用记忆化搜索来实现数位 DP。基本步骤如下:
 
-基本步骤如下:
-
-1. 将数字 $n$ 转为二进制数组 $a$,其中 $a[1]$ 为最低位,而 $a[len]$ 为最高位;
-1. 根据题目信息,设计函数 $dfs()$,对于本题,我们定义 $dfs(pos, pre, limit)$,答案为 $dfs(len, 1, true)$。
+1. 将数字 $n$ 转为二进制字符串 $s$;
+1. 根据题目信息,设计函数 $\textit{dfs}()$,对于本题,我们定义 $\textit{dfs}(\textit{pos}, \textit{pre}, \textit{limit})$,答案为 $\textit{dfs}(\textit{0}, 0, \textit{true})$。
 
 其中:
 
--   `pos` 表示数字的位数,从末位或者第一位开始,一般根据题目的数字构造性质来选择顺序。对于本题,我们选择从高位开始,因此,`pos` 的初始值为 `len`;
+-   `pos` 表示数字的位数,我们从数字的最高位开始,即二进制字符串的首字符;
 -   `pre` 表示当前数字二进制位上的数字,对于本题,`pre` 的初始值为 `0`;
--   `limit` 表示可填的数字的限制,如果无限制,那么可以选择 $[0,1]$,否则,只能选择 $[0,..a[pos]]$。如果 `limit` 为 `true` 且已经取到了能取到的最大值,那么下一个 `limit` 同样为 `true`;如果 `limit` 为 `true` 但是还没有取到最大值,或者 `limit` 为 `false`,那么下一个 `limit` 为 `false`。
+-   `limit` 表示可填的数字的限制,如果无限制,那么可以选择 $[0,1]$,否则,只能选择 $[0,..s[\textit{pos}]]$。
 
 关于函数的实现细节,可以参考下面的代码。
 
-时间复杂度 $O(\log n)$。
+时间复杂度 $O(\log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为题目给定的数字。
 
 相似题目:
 
@@ -109,61 +107,50 @@ $$
 class Solution:
     def findIntegers(self, n: int) -> int:
         @cache
-        def dfs(pos, pre, limit):
-            if pos <= 0:
+        def dfs(pos: int, pre: int, limit: bool) -> int:
+            if pos == len(s):
                 return 1
-            up = a[pos] if limit else 1
+            up = int(s[pos]) if limit else 1
             ans = 0
             for i in range(up + 1):
                 if pre == 1 and i == 1:
                     continue
-                ans += dfs(pos - 1, i, limit and i == up)
+                ans += dfs(pos + 1, i, limit and i == up)
             return ans
 
-        a = [0] * 33
-        l = 0
-        while n:
-            l += 1
-            a[l] = n & 1
-            n >>= 1
-        return dfs(l, 0, True)
+        s = bin(n)[2:]
+        return dfs(0, 0, True)
 ```
 
 #### Java
 
 ```java
 class Solution {
-    private int[] a = new int[33];
-    private int[][] dp = new int[33][2];
+    private char[] s;
+    private Integer[][] f;
 
     public int findIntegers(int n) {
-        int len = 0;
-        while (n > 0) {
-            a[++len] = n & 1;
-            n >>= 1;
-        }
-        for (var e : dp) {
-            Arrays.fill(e, -1);
-        }
-        return dfs(len, 0, true);
+        s = Integer.toBinaryString(n).toCharArray();
+        f = new Integer[s.length][2];
+        return dfs(0, 0, true);
     }
 
     private int dfs(int pos, int pre, boolean limit) {
-        if (pos <= 0) {
+        if (pos >= s.length) {
             return 1;
         }
-        if (!limit && dp[pos][pre] != -1) {
-            return dp[pos][pre];
+        if (!limit && f[pos][pre] != null) {
+            return f[pos][pre];
         }
-        int up = limit ? a[pos] : 1;
+        int up = limit ? s[pos] - '0' : 1;
         int ans = 0;
         for (int i = 0; i <= up; ++i) {
             if (!(pre == 1 && i == 1)) {
-                ans += dfs(pos - 1, i, limit && i == up);
+                ans += dfs(pos + 1, i, limit && i == up);
             }
         }
         if (!limit) {
-            dp[pos][pre] = ans;
+            f[pos][pre] = ans;
         }
         return ans;
     }
@@ -175,37 +162,32 @@ class Solution {
 ```cpp
 class Solution {
 public:
-    int a[33];
-    int dp[33][2];
-
     int findIntegers(int n) {
-        int len = 0;
-        while (n) {
-            a[++len] = n & 1;
-            n >>= 1;
-        }
-        memset(dp, -1, sizeof dp);
-        return dfs(len, 0, true);
-    }
-
-    int dfs(int pos, int pre, bool limit) {
-        if (pos <= 0) {
-            return 1;
-        }
-        if (!limit && dp[pos][pre] != -1) {
-            return dp[pos][pre];
-        }
-        int ans = 0;
-        int up = limit ? a[pos] : 1;
-        for (int i = 0; i <= up; ++i) {
-            if (!(pre == 1 && i == 1)) {
-                ans += dfs(pos - 1, i, limit && i == up);
+        string s = bitset<32>(n).to_string();
+        s = s.substr(s.find('1'));
+        int m = s.size();
+        int f[m][2];
+        memset(f, -1, sizeof(f));
+        auto dfs = [&](auto&& dfs, int pos, int pre, bool limit) -> int {
+            if (pos >= m) {
+                return 1;
             }
-        }
-        if (!limit) {
-            dp[pos][pre] = ans;
-        }
-        return ans;
+            if (!limit && f[pos][pre] != -1) {
+                return f[pos][pre];
+            }
+            int up = limit ? s[pos] - '0' : 1;
+            int ans = 0;
+            for (int i = 0; i <= up; ++i) {
+                if (!(pre == 1 && i == 1)) {
+                    ans += dfs(dfs, pos + 1, i, limit && i == up);
+                }
+            }
+            if (!limit) {
+                f[pos][pre] = ans;
+            }
+            return ans;
+        };
+        return dfs(dfs, 0, 0, true);
     }
 };
 ```
@@ -214,41 +196,68 @@ public:
 
 ```go
 func findIntegers(n int) int {
-	a := make([]int, 33)
-	dp := make([][2]int, 33)
-	for i := range dp {
-		dp[i] = [2]int{-1, -1}
-	}
-	l := 0
-	for n > 0 {
-		l++
-		a[l] = n & 1
-		n >>= 1
+	s := strconv.FormatInt(int64(n), 2)
+	m := len(s)
+	f := make([][]int, m)
+	for i := range f {
+		f[i] = []int{-1, -1}
 	}
 	var dfs func(int, int, bool) int
-	dfs = func(pos, pre int, limit bool) int {
-		if pos <= 0 {
+	dfs = func(pos int, pre int, limit bool) int {
+		if pos >= m {
 			return 1
 		}
-		if !limit && dp[pos][pre] != -1 {
-			return dp[pos][pre]
+		if !limit && f[pos][pre] != -1 {
+			return f[pos][pre]
 		}
 		up := 1
 		if limit {
-			up = a[pos]
+			up = int(s[pos] - '0')
 		}
 		ans := 0
 		for i := 0; i <= up; i++ {
 			if !(pre == 1 && i == 1) {
-				ans += dfs(pos-1, i, limit && i == up)
+				ans += dfs(pos+1, i, limit && i == up)
 			}
 		}
 		if !limit {
-			dp[pos][pre] = ans
+			f[pos][pre] = ans
 		}
 		return ans
 	}
-	return dfs(l, 0, true)
+	return dfs(0, 0, true)
+}
+```
+
+#### TypeScript
+
+```ts
+function findIntegers(n: number): number {
+    const s = n.toString(2);
+    const m = s.length;
+    const f: number[][] = Array.from({ length: m }, () => [-1, -1]);
+
+    function dfs(pos: number, pre: number, limit: boolean): number {
+        if (pos >= m) {
+            return 1;
+        }
+        if (!limit && f[pos][pre] !== -1) {
+            return f[pos][pre];
+        }
+        const up = limit ? parseInt(s[pos]) : 1;
+        let ans = 0;
+        for (let i = 0; i <= up; ++i) {
+            if (!(pre === 1 && i === 1)) {
+                ans += dfs(pos + 1, i, limit && i === up);
+            }
+        }
+        if (!limit) {
+            f[pos][pre] = ans;
+        }
+        return ans;
+    }
+
+    return dfs(0, 0, true);
 }
 ```
 
diff --git a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README_EN.md b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README_EN.md
index 73100c20f7d2d..9a8d4850c9bc3 100644
--- a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README_EN.md	
+++ b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README_EN.md	
@@ -32,7 +32,7 @@ Here are the non-negative integers <= 5 with their corresponding binary repre
 3 : 11
 4 : 100
 5 : 101
-Among them, only integer 3 disobeys the rule (two consecutive ones) and the other 5 satisfy the rule. 
+Among them, only integer 3 disobeys the rule (two consecutive ones) and the other 5 satisfy the rule.
 

Example 2:

@@ -62,7 +62,41 @@ Among them, only integer 3 disobeys the rule (two consecutive ones) and the othe -### Solution 1 +### Solution 1: Digit DP + +This problem is essentially about finding the number of numbers in the given interval $[l,..r]$ whose binary representation does not contain consecutive $1$s. The count is related to the number of digits and the digits in each binary position. We can solve this problem using the digit DP approach. In digit DP, the size of the number has little impact on the complexity. + +For the interval $[l,..r]$ problem, we generally convert it to the problem of $[0,..r]$ and then subtract the problem of $[0,..l - 1]$, i.e.: + +$$ +ans = \sum_{i=0}^{r} ans_i - \sum_{i=0}^{l-1} ans_i +$$ + +However, for this problem, we only need to find the value for the interval $[0,..r]$. + +Here we use memoization to implement digit DP. The basic steps are as follows: + +1. Convert the number $n$ to a binary string $s$; +1. According to the problem information, design the function $\textit{dfs}()$. For this problem, we define $\textit{dfs}(\textit{pos}, \textit{pre}, \textit{limit})$, and the answer is $\textit{dfs}(\textit{0}, 0, \textit{true})$. + +Where: + +- `pos` represents the digit position, starting from the highest digit of the number, i.e., the first character of the binary string; +- `pre` represents the digit at the current binary position. For this problem, the initial value of `pre` is `0`; +- `limit` represents the restriction on the digits that can be filled. If there is no restriction, then $[0,1]$ can be chosen; otherwise, only $[0,..s[\textit{pos}]]$ can be chosen. + +For the implementation details of the function, refer to the code below. + +Time complexity is $O(\log n)$, and space complexity is $O(\log n)$. Here, $n$ is the number given in the problem. + +Similar problems: + +- [233. Number of Digit One](https://github.com/doocs/leetcode/blob/main/solution/0200-0299/0233.Number%20of%20Digit%20One/README_EN.md) +- [357. Count Numbers with Unique Digits](https://github.com/doocs/leetcode/blob/main/solution/0300-0399/0357.Count%20Numbers%20with%20Unique%20Digits/README_EN.md) +- [788. Rotated Digits](https://github.com/doocs/leetcode/blob/main/solution/0700-0799/0788.Rotated%20Digits/README_EN.md) +- [902. Numbers At Most N Given Digit Set](https://github.com/doocs/leetcode/blob/main/solution/0900-0999/0902.Numbers%20At%20Most%20N%20Given%20Digit%20Set/README_EN.md) +- [1012. Numbers With Repeated Digits](https://github.com/doocs/leetcode/blob/main/solution/1000-1099/1012.Numbers%20With%20Repeated%20Digits/README_EN.md) +- [2376. Count Special Integers](https://github.com/doocs/leetcode/blob/main/solution/2300-2399/2376.Count%20Special%20Integers/README_EN.md) @@ -72,61 +106,50 @@ Among them, only integer 3 disobeys the rule (two consecutive ones) and the othe class Solution: def findIntegers(self, n: int) -> int: @cache - def dfs(pos, pre, limit): - if pos <= 0: + def dfs(pos: int, pre: int, limit: bool) -> int: + if pos == len(s): return 1 - up = a[pos] if limit else 1 + up = int(s[pos]) if limit else 1 ans = 0 for i in range(up + 1): if pre == 1 and i == 1: continue - ans += dfs(pos - 1, i, limit and i == up) + ans += dfs(pos + 1, i, limit and i == up) return ans - a = [0] * 33 - l = 0 - while n: - l += 1 - a[l] = n & 1 - n >>= 1 - return dfs(l, 0, True) + s = bin(n)[2:] + return dfs(0, 0, True) ``` #### Java ```java class Solution { - private int[] a = new int[33]; - private int[][] dp = new int[33][2]; + private char[] s; + private Integer[][] f; public int findIntegers(int n) { - int len = 0; - while (n > 0) { - a[++len] = n & 1; - n >>= 1; - } - for (var e : dp) { - Arrays.fill(e, -1); - } - return dfs(len, 0, true); + s = Integer.toBinaryString(n).toCharArray(); + f = new Integer[s.length][2]; + return dfs(0, 0, true); } private int dfs(int pos, int pre, boolean limit) { - if (pos <= 0) { + if (pos >= s.length) { return 1; } - if (!limit && dp[pos][pre] != -1) { - return dp[pos][pre]; + if (!limit && f[pos][pre] != null) { + return f[pos][pre]; } - int up = limit ? a[pos] : 1; + int up = limit ? s[pos] - '0' : 1; int ans = 0; for (int i = 0; i <= up; ++i) { if (!(pre == 1 && i == 1)) { - ans += dfs(pos - 1, i, limit && i == up); + ans += dfs(pos + 1, i, limit && i == up); } } if (!limit) { - dp[pos][pre] = ans; + f[pos][pre] = ans; } return ans; } @@ -138,37 +161,32 @@ class Solution { ```cpp class Solution { public: - int a[33]; - int dp[33][2]; - int findIntegers(int n) { - int len = 0; - while (n) { - a[++len] = n & 1; - n >>= 1; - } - memset(dp, -1, sizeof dp); - return dfs(len, 0, true); - } - - int dfs(int pos, int pre, bool limit) { - if (pos <= 0) { - return 1; - } - if (!limit && dp[pos][pre] != -1) { - return dp[pos][pre]; - } - int ans = 0; - int up = limit ? a[pos] : 1; - for (int i = 0; i <= up; ++i) { - if (!(pre == 1 && i == 1)) { - ans += dfs(pos - 1, i, limit && i == up); + string s = bitset<32>(n).to_string(); + s = s.substr(s.find('1')); + int m = s.size(); + int f[m][2]; + memset(f, -1, sizeof(f)); + auto dfs = [&](auto&& dfs, int pos, int pre, bool limit) -> int { + if (pos >= m) { + return 1; } - } - if (!limit) { - dp[pos][pre] = ans; - } - return ans; + if (!limit && f[pos][pre] != -1) { + return f[pos][pre]; + } + int up = limit ? s[pos] - '0' : 1; + int ans = 0; + for (int i = 0; i <= up; ++i) { + if (!(pre == 1 && i == 1)) { + ans += dfs(dfs, pos + 1, i, limit && i == up); + } + } + if (!limit) { + f[pos][pre] = ans; + } + return ans; + }; + return dfs(dfs, 0, 0, true); } }; ``` @@ -177,41 +195,68 @@ public: ```go func findIntegers(n int) int { - a := make([]int, 33) - dp := make([][2]int, 33) - for i := range dp { - dp[i] = [2]int{-1, -1} - } - l := 0 - for n > 0 { - l++ - a[l] = n & 1 - n >>= 1 + s := strconv.FormatInt(int64(n), 2) + m := len(s) + f := make([][]int, m) + for i := range f { + f[i] = []int{-1, -1} } var dfs func(int, int, bool) int - dfs = func(pos, pre int, limit bool) int { - if pos <= 0 { + dfs = func(pos int, pre int, limit bool) int { + if pos >= m { return 1 } - if !limit && dp[pos][pre] != -1 { - return dp[pos][pre] + if !limit && f[pos][pre] != -1 { + return f[pos][pre] } up := 1 if limit { - up = a[pos] + up = int(s[pos] - '0') } ans := 0 for i := 0; i <= up; i++ { if !(pre == 1 && i == 1) { - ans += dfs(pos-1, i, limit && i == up) + ans += dfs(pos+1, i, limit && i == up) } } if !limit { - dp[pos][pre] = ans + f[pos][pre] = ans } return ans } - return dfs(l, 0, true) + return dfs(0, 0, true) +} +``` + +#### TypeScript + +```ts +function findIntegers(n: number): number { + const s = n.toString(2); + const m = s.length; + const f: number[][] = Array.from({ length: m }, () => [-1, -1]); + + function dfs(pos: number, pre: number, limit: boolean): number { + if (pos >= m) { + return 1; + } + if (!limit && f[pos][pre] !== -1) { + return f[pos][pre]; + } + const up = limit ? parseInt(s[pos]) : 1; + let ans = 0; + for (let i = 0; i <= up; ++i) { + if (!(pre === 1 && i === 1)) { + ans += dfs(pos + 1, i, limit && i === up); + } + } + if (!limit) { + f[pos][pre] = ans; + } + return ans; + } + + return dfs(0, 0, true); } ``` diff --git a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.cpp b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.cpp index 8bfb4af82c9a4..1fcd6f6000aa3 100644 --- a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.cpp +++ b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.cpp @@ -1,35 +1,30 @@ class Solution { public: - int a[33]; - int dp[33][2]; - int findIntegers(int n) { - int len = 0; - while (n) { - a[++len] = n & 1; - n >>= 1; - } - memset(dp, -1, sizeof dp); - return dfs(len, 0, true); - } - - int dfs(int pos, int pre, bool limit) { - if (pos <= 0) { - return 1; - } - if (!limit && dp[pos][pre] != -1) { - return dp[pos][pre]; - } - int ans = 0; - int up = limit ? a[pos] : 1; - for (int i = 0; i <= up; ++i) { - if (!(pre == 1 && i == 1)) { - ans += dfs(pos - 1, i, limit && i == up); + string s = bitset<32>(n).to_string(); + s = s.substr(s.find('1')); + int m = s.size(); + int f[m][2]; + memset(f, -1, sizeof(f)); + auto dfs = [&](auto&& dfs, int pos, int pre, bool limit) -> int { + if (pos >= m) { + return 1; + } + if (!limit && f[pos][pre] != -1) { + return f[pos][pre]; + } + int up = limit ? s[pos] - '0' : 1; + int ans = 0; + for (int i = 0; i <= up; ++i) { + if (!(pre == 1 && i == 1)) { + ans += dfs(dfs, pos + 1, i, limit && i == up); + } + } + if (!limit) { + f[pos][pre] = ans; } - } - if (!limit) { - dp[pos][pre] = ans; - } - return ans; + return ans; + }; + return dfs(dfs, 0, 0, true); } -}; \ No newline at end of file +}; diff --git a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.go b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.go index de984b678cdea..e68031cff719b 100644 --- a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.go +++ b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.go @@ -1,37 +1,32 @@ func findIntegers(n int) int { - a := make([]int, 33) - dp := make([][2]int, 33) - for i := range dp { - dp[i] = [2]int{-1, -1} - } - l := 0 - for n > 0 { - l++ - a[l] = n & 1 - n >>= 1 + s := strconv.FormatInt(int64(n), 2) + m := len(s) + f := make([][]int, m) + for i := range f { + f[i] = []int{-1, -1} } var dfs func(int, int, bool) int - dfs = func(pos, pre int, limit bool) int { - if pos <= 0 { + dfs = func(pos int, pre int, limit bool) int { + if pos >= m { return 1 } - if !limit && dp[pos][pre] != -1 { - return dp[pos][pre] + if !limit && f[pos][pre] != -1 { + return f[pos][pre] } up := 1 if limit { - up = a[pos] + up = int(s[pos] - '0') } ans := 0 for i := 0; i <= up; i++ { if !(pre == 1 && i == 1) { - ans += dfs(pos-1, i, limit && i == up) + ans += dfs(pos+1, i, limit && i == up) } } if !limit { - dp[pos][pre] = ans + f[pos][pre] = ans } return ans } - return dfs(l, 0, true) -} \ No newline at end of file + return dfs(0, 0, true) +} diff --git a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.java b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.java index a2ee46c7d5f9e..62eca73165333 100644 --- a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.java +++ b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.java @@ -1,36 +1,30 @@ class Solution { - private int[] a = new int[33]; - private int[][] dp = new int[33][2]; + private char[] s; + private Integer[][] f; public int findIntegers(int n) { - int len = 0; - while (n > 0) { - a[++len] = n & 1; - n >>= 1; - } - for (var e : dp) { - Arrays.fill(e, -1); - } - return dfs(len, 0, true); + s = Integer.toBinaryString(n).toCharArray(); + f = new Integer[s.length][2]; + return dfs(0, 0, true); } private int dfs(int pos, int pre, boolean limit) { - if (pos <= 0) { + if (pos >= s.length) { return 1; } - if (!limit && dp[pos][pre] != -1) { - return dp[pos][pre]; + if (!limit && f[pos][pre] != null) { + return f[pos][pre]; } - int up = limit ? a[pos] : 1; + int up = limit ? s[pos] - '0' : 1; int ans = 0; for (int i = 0; i <= up; ++i) { if (!(pre == 1 && i == 1)) { - ans += dfs(pos - 1, i, limit && i == up); + ans += dfs(pos + 1, i, limit && i == up); } } if (!limit) { - dp[pos][pre] = ans; + f[pos][pre] = ans; } return ans; } -} \ No newline at end of file +} diff --git a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.py b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.py index 82139a40c2f50..9553346958036 100644 --- a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.py +++ b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.py @@ -1,21 +1,16 @@ class Solution: def findIntegers(self, n: int) -> int: @cache - def dfs(pos, pre, limit): - if pos <= 0: + def dfs(pos: int, pre: int, limit: bool) -> int: + if pos == len(s): return 1 - up = a[pos] if limit else 1 + up = int(s[pos]) if limit else 1 ans = 0 for i in range(up + 1): if pre == 1 and i == 1: continue - ans += dfs(pos - 1, i, limit and i == up) + ans += dfs(pos + 1, i, limit and i == up) return ans - a = [0] * 33 - l = 0 - while n: - l += 1 - a[l] = n & 1 - n >>= 1 - return dfs(l, 0, True) + s = bin(n)[2:] + return dfs(0, 0, True) diff --git a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.ts b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.ts new file mode 100644 index 0000000000000..e22bdb39fb1b2 --- /dev/null +++ b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.ts @@ -0,0 +1,27 @@ +function findIntegers(n: number): number { + const s = n.toString(2); + const m = s.length; + const f: number[][] = Array.from({ length: m }, () => [-1, -1]); + + function dfs(pos: number, pre: number, limit: boolean): number { + if (pos >= m) { + return 1; + } + if (!limit && f[pos][pre] !== -1) { + return f[pos][pre]; + } + const up = limit ? parseInt(s[pos]) : 1; + let ans = 0; + for (let i = 0; i <= up; ++i) { + if (!(pre === 1 && i === 1)) { + ans += dfs(pos + 1, i, limit && i === up); + } + } + if (!limit) { + f[pos][pre] = ans; + } + return ans; + } + + return dfs(0, 0, true); +}