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 cc1828da9c51a..7188711b1fb7e 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
@@ -77,18 +77,22 @@ $$
 
 这里我们用记忆化搜索来实现数位 DP。基本步骤如下:
 
-1. 将数字 $n$ 转为二进制字符串 $s$;
-1. 根据题目信息,设计函数 $\textit{dfs}()$,对于本题,我们定义 $\textit{dfs}(\textit{pos}, \textit{pre}, \textit{limit})$,答案为 $\textit{dfs}(\textit{0}, 0, \textit{true})$。
+我们首先获取数字 $n$ 的二进制长度,记为 $m$。然后根据题目信息,我们设计函数 $\textit{dfs}(i, \textit{pre}, \textit{limit})$,其中:
 
-其中:
+-   数字 $i$ 表示当前搜索到的位置,我们从数字的最高位开始搜索,即二进制字符串的首字符;
+-   数字 $\textit{pre}$ 表示上一个数字二进制位上的数字,对于本题,$\textit{pre}$ 的初始值为 $0$;
+-   布尔值 $\textit{limit}$ 表示可填的数字的限制,如果无限制,那么可以选择 $[0,1]$,否则,只能选择 $[0, \textit{up}]$。
 
--   `pos` 表示数字的位数,我们从数字的最高位开始,即二进制字符串的首字符;
--   `pre` 表示当前数字二进制位上的数字,对于本题,`pre` 的初始值为 `0`;
--   `limit` 表示可填的数字的限制,如果无限制,那么可以选择 $[0,1]$,否则,只能选择 $[0,..s[\textit{pos}]]$。
+函数的执行过程如下:
 
-关于函数的实现细节,可以参考下面的代码。
+如果 $i$ 超过了数字 $n$ 的长度,即 $i \lt 0$,说明搜索结束,直接返回 $1$。否则,我们从 $0$ 到 $\textit{up}$ 枚举位置 $i$ 的数字 $j$,对于每一个 $j$:
 
-时间复杂度 $O(\log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为题目给定的数字。
+-   如果 $\textit{pre}$ 和 $j$ 都为 $1$,说明有连续的 $1$,直接跳过;
+-   否则,我们递归到下一层,更新 $\textit{pre}$ 为 $j$,并将 $\textit{limit}$ 更新为 $\textit{limit}$ 与 $j$ 是否等于 $\textit{up}$ 的逻辑与。
+
+最后,我们将所有递归到下一层的结果累加,即为答案。
+
+时间复杂度 $O(\log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为题目给定的正整数。
 
 相似题目:
 
@@ -107,50 +111,51 @@ $$
 class Solution:
     def findIntegers(self, n: int) -> int:
         @cache
-        def dfs(pos: int, pre: int, limit: bool) -> int:
-            if pos == len(s):
+        def dfs(i: int, pre: int, limit: bool) -> int:
+            if i < 0:
                 return 1
-            up = int(s[pos]) if limit else 1
+            up = (n >> i & 1) if limit else 1
             ans = 0
-            for i in range(up + 1):
-                if pre == 1 and i == 1:
+            for j in range(up + 1):
+                if pre and j:
                     continue
-                ans += dfs(pos + 1, i, limit and i == up)
+                ans += dfs(i - 1, j, limit and j == up)
             return ans
 
-        s = bin(n)[2:]
-        return dfs(0, 0, True)
+        return dfs(n.bit_length() - 1, 0, True)
 ```
 
 #### Java
 
 ```java
 class Solution {
-    private char[] s;
+    private int n;
     private Integer[][] f;
 
     public int findIntegers(int n) {
-        s = Integer.toBinaryString(n).toCharArray();
-        f = new Integer[s.length][2];
-        return dfs(0, 0, true);
+        this.n = n;
+        int m = Integer.SIZE - Integer.numberOfLeadingZeros(n);
+        f = new Integer[m][2];
+        return dfs(m - 1, 0, true);
     }
 
-    private int dfs(int pos, int pre, boolean limit) {
-        if (pos >= s.length) {
+    private int dfs(int i, int pre, boolean limit) {
+        if (i < 0) {
             return 1;
         }
-        if (!limit && f[pos][pre] != null) {
-            return f[pos][pre];
+        if (!limit && f[i][pre] != null) {
+            return f[i][pre];
         }
-        int up = limit ? s[pos] - '0' : 1;
+        int up = limit ? (n >> i & 1) : 1;
         int ans = 0;
-        for (int i = 0; i <= up; ++i) {
-            if (!(pre == 1 && i == 1)) {
-                ans += dfs(pos + 1, i, limit && i == up);
+        for (int j = 0; j <= up; ++j) {
+            if (j == 1 && pre == 1) {
+                continue;
             }
+            ans += dfs(i - 1, j, limit && j == up);
         }
         if (!limit) {
-            f[pos][pre] = ans;
+            f[i][pre] = ans;
         }
         return ans;
     }
@@ -163,31 +168,30 @@ class Solution {
 class Solution {
 public:
     int findIntegers(int n) {
-        string s = bitset<32>(n).to_string();
-        s = s.substr(s.find('1'));
-        int m = s.size();
+        int m = 32 - __builtin_clz(n);
         int f[m][2];
         memset(f, -1, sizeof(f));
-        auto dfs = [&](auto&& dfs, int pos, int pre, bool limit) -> int {
-            if (pos >= m) {
+        auto dfs = [&](auto&& dfs, int i, int pre, bool limit) -> int {
+            if (i < 0) {
                 return 1;
             }
-            if (!limit && f[pos][pre] != -1) {
-                return f[pos][pre];
+            if (!limit && f[i][pre] != -1) {
+                return f[i][pre];
             }
-            int up = limit ? s[pos] - '0' : 1;
+            int up = limit ? (n >> i & 1) : 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);
+            for (int j = 0; j <= up; ++j) {
+                if (j && pre) {
+                    continue;
                 }
+                ans += dfs(dfs, i - 1, j, limit && j == up);
             }
             if (!limit) {
-                f[pos][pre] = ans;
+                f[i][pre] = ans;
             }
             return ans;
         };
-        return dfs(dfs, 0, 0, true);
+        return dfs(dfs, m - 1, 0, true);
     }
 };
 ```
@@ -196,36 +200,36 @@ public:
 
 ```go
 func findIntegers(n int) int {
-	s := strconv.FormatInt(int64(n), 2)
-	m := len(s)
-	f := make([][]int, m)
+	m := bits.Len(uint(n))
+	f := make([][2]int, m)
 	for i := range f {
-		f[i] = []int{-1, -1}
+		f[i] = [2]int{-1, -1}
 	}
-	var dfs func(int, int, bool) int
-	dfs = func(pos int, pre int, limit bool) int {
-		if pos >= m {
+	var dfs func(i, pre int, limit bool) int
+	dfs = func(i, pre int, limit bool) int {
+		if i < 0 {
 			return 1
 		}
-		if !limit && f[pos][pre] != -1 {
-			return f[pos][pre]
+		if !limit && f[i][pre] != -1 {
+			return f[i][pre]
 		}
 		up := 1
 		if limit {
-			up = int(s[pos] - '0')
+			up = n >> i & 1
 		}
 		ans := 0
-		for i := 0; i <= up; i++ {
-			if !(pre == 1 && i == 1) {
-				ans += dfs(pos+1, i, limit && i == up)
+		for j := 0; j <= up; j++ {
+			if j == 1 && pre == 1 {
+				continue
 			}
+			ans += dfs(i-1, j, limit && j == up)
 		}
 		if !limit {
-			f[pos][pre] = ans
+			f[i][pre] = ans
 		}
 		return ans
 	}
-	return dfs(0, 0, true)
+	return dfs(m-1, 0, true)
 }
 ```
 
@@ -233,31 +237,29 @@ func findIntegers(n int) int {
 
 ```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) {
+    const m = n.toString(2).length;
+    const f: number[][] = Array.from({ length: m }, () => Array(2).fill(-1));
+    const dfs = (i: number, pre: number, limit: boolean): number => {
+        if (i < 0) {
             return 1;
         }
-        if (!limit && f[pos][pre] !== -1) {
-            return f[pos][pre];
+        if (!limit && f[i][pre] !== -1) {
+            return f[i][pre];
         }
-        const up = limit ? parseInt(s[pos]) : 1;
+        const up = limit ? (n >> i) & 1 : 1;
         let ans = 0;
-        for (let i = 0; i <= up; ++i) {
-            if (!(pre === 1 && i === 1)) {
-                ans += dfs(pos + 1, i, limit && i === up);
+        for (let j = 0; j <= up; ++j) {
+            if (pre === 1 && j === 1) {
+                continue;
             }
+            ans += dfs(i - 1, j, limit && j === up);
         }
         if (!limit) {
-            f[pos][pre] = ans;
+            f[i][pre] = ans;
         }
         return ans;
-    }
-
-    return dfs(0, 0, true);
+    };
+    return dfs(m - 1, 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 4d1cbe0d9b1f2..470a1d720dd90 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:

@@ -64,30 +64,34 @@ Among them, only integer 3 disobeys the rule (two consecutive ones) and the othe ### 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. +This problem essentially asks for the number of numbers in the given range $[l, ..r]$ whose binary representation does not contain consecutive $1$s. The count is related to the number of digits and the value of each binary digit. We can use the concept of Digit DP to solve this problem. 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.: +For the range $[l, ..r]$ problem, we generally convert it to the problem of $[0, ..r]$ and then subtract the result 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]$. +However, for this problem, we only need to find the value for the range $[0, ..r]$. -Here we use memoization to implement digit DP. The basic steps are as follows: +Here, we use memoized search 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})$. +First, we get the binary length of the number $n$, denoted as $m$. Then, based on the problem information, we design a function $\textit{dfs}(i, \textit{pre}, \textit{limit})$, where: -Where: +- The digit $i$ represents the current position being searched, starting from the highest digit, i.e., the first character of the binary string. +- The digit $\textit{pre}$ represents the digit at the previous binary position. For this problem, the initial value of $\textit{pre}$ is $0$. +- The boolean $\textit{limit}$ indicates whether the digits that can be filled are restricted. If there is no restriction, then we can choose $[0,1]$. Otherwise, we can only choose $[0, \textit{up}]$. -- `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. +The function executes as follows: -For the implementation details of the function, refer to the code below. +If $i$ exceeds the length of the number $n$, i.e., $i < 0$, it means the search is over, directly return $1$. Otherwise, we enumerate the digits $j$ from $0$ to $\textit{up}$ for the position $i$. For each $j$: -Time complexity is $O(\log n)$, and space complexity is $O(\log n)$. Here, $n$ is the number given in the problem. +- If both $\textit{pre}$ and $j$ are $1$, it means there are consecutive $1$, so we skip it. +- Otherwise, we recurse to the next level, update $\textit{pre}$ to $j$, and update $\textit{limit}$ to the logical AND of $\textit{limit}$ and whether $j$ equals $\textit{up}$. + +Finally, we sum all the results from the recursive calls to the next level, which is the answer. + +The time complexity is $O(\log n)$, and the space complexity is $O(\log n)$. Here, $n$ is the given positive integer. Similar problems: @@ -106,50 +110,51 @@ Similar problems: class Solution: def findIntegers(self, n: int) -> int: @cache - def dfs(pos: int, pre: int, limit: bool) -> int: - if pos == len(s): + def dfs(i: int, pre: int, limit: bool) -> int: + if i < 0: return 1 - up = int(s[pos]) if limit else 1 + up = (n >> i & 1) if limit else 1 ans = 0 - for i in range(up + 1): - if pre == 1 and i == 1: + for j in range(up + 1): + if pre and j: continue - ans += dfs(pos + 1, i, limit and i == up) + ans += dfs(i - 1, j, limit and j == up) return ans - s = bin(n)[2:] - return dfs(0, 0, True) + return dfs(n.bit_length() - 1, 0, True) ``` #### Java ```java class Solution { - private char[] s; + private int n; private Integer[][] f; public int findIntegers(int n) { - s = Integer.toBinaryString(n).toCharArray(); - f = new Integer[s.length][2]; - return dfs(0, 0, true); + this.n = n; + int m = Integer.SIZE - Integer.numberOfLeadingZeros(n); + f = new Integer[m][2]; + return dfs(m - 1, 0, true); } - private int dfs(int pos, int pre, boolean limit) { - if (pos >= s.length) { + private int dfs(int i, int pre, boolean limit) { + if (i < 0) { return 1; } - if (!limit && f[pos][pre] != null) { - return f[pos][pre]; + if (!limit && f[i][pre] != null) { + return f[i][pre]; } - int up = limit ? s[pos] - '0' : 1; + int up = limit ? (n >> i & 1) : 1; int ans = 0; - for (int i = 0; i <= up; ++i) { - if (!(pre == 1 && i == 1)) { - ans += dfs(pos + 1, i, limit && i == up); + for (int j = 0; j <= up; ++j) { + if (j == 1 && pre == 1) { + continue; } + ans += dfs(i - 1, j, limit && j == up); } if (!limit) { - f[pos][pre] = ans; + f[i][pre] = ans; } return ans; } @@ -162,31 +167,30 @@ class Solution { class Solution { public: int findIntegers(int n) { - string s = bitset<32>(n).to_string(); - s = s.substr(s.find('1')); - int m = s.size(); + int m = 32 - __builtin_clz(n); int f[m][2]; memset(f, -1, sizeof(f)); - auto dfs = [&](auto&& dfs, int pos, int pre, bool limit) -> int { - if (pos >= m) { + auto dfs = [&](auto&& dfs, int i, int pre, bool limit) -> int { + if (i < 0) { return 1; } - if (!limit && f[pos][pre] != -1) { - return f[pos][pre]; + if (!limit && f[i][pre] != -1) { + return f[i][pre]; } - int up = limit ? s[pos] - '0' : 1; + int up = limit ? (n >> i & 1) : 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); + for (int j = 0; j <= up; ++j) { + if (j && pre) { + continue; } + ans += dfs(dfs, i - 1, j, limit && j == up); } if (!limit) { - f[pos][pre] = ans; + f[i][pre] = ans; } return ans; }; - return dfs(dfs, 0, 0, true); + return dfs(dfs, m - 1, 0, true); } }; ``` @@ -195,36 +199,36 @@ public: ```go func findIntegers(n int) int { - s := strconv.FormatInt(int64(n), 2) - m := len(s) - f := make([][]int, m) + m := bits.Len(uint(n)) + f := make([][2]int, m) for i := range f { - f[i] = []int{-1, -1} + f[i] = [2]int{-1, -1} } - var dfs func(int, int, bool) int - dfs = func(pos int, pre int, limit bool) int { - if pos >= m { + var dfs func(i, pre int, limit bool) int + dfs = func(i, pre int, limit bool) int { + if i < 0 { return 1 } - if !limit && f[pos][pre] != -1 { - return f[pos][pre] + if !limit && f[i][pre] != -1 { + return f[i][pre] } up := 1 if limit { - up = int(s[pos] - '0') + up = n >> i & 1 } ans := 0 - for i := 0; i <= up; i++ { - if !(pre == 1 && i == 1) { - ans += dfs(pos+1, i, limit && i == up) + for j := 0; j <= up; j++ { + if j == 1 && pre == 1 { + continue } + ans += dfs(i-1, j, limit && j == up) } if !limit { - f[pos][pre] = ans + f[i][pre] = ans } return ans } - return dfs(0, 0, true) + return dfs(m-1, 0, true) } ``` @@ -232,31 +236,29 @@ func findIntegers(n int) int { ```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) { + const m = n.toString(2).length; + const f: number[][] = Array.from({ length: m }, () => Array(2).fill(-1)); + const dfs = (i: number, pre: number, limit: boolean): number => { + if (i < 0) { return 1; } - if (!limit && f[pos][pre] !== -1) { - return f[pos][pre]; + if (!limit && f[i][pre] !== -1) { + return f[i][pre]; } - const up = limit ? parseInt(s[pos]) : 1; + const up = limit ? (n >> i) & 1 : 1; let ans = 0; - for (let i = 0; i <= up; ++i) { - if (!(pre === 1 && i === 1)) { - ans += dfs(pos + 1, i, limit && i === up); + for (let j = 0; j <= up; ++j) { + if (pre === 1 && j === 1) { + continue; } + ans += dfs(i - 1, j, limit && j === up); } if (!limit) { - f[pos][pre] = ans; + f[i][pre] = ans; } return ans; - } - - return dfs(0, 0, true); + }; + return dfs(m - 1, 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 1fcd6f6000aa3..ada429667657b 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,30 +1,29 @@ class Solution { public: int findIntegers(int n) { - string s = bitset<32>(n).to_string(); - s = s.substr(s.find('1')); - int m = s.size(); + int m = 32 - __builtin_clz(n); int f[m][2]; memset(f, -1, sizeof(f)); - auto dfs = [&](auto&& dfs, int pos, int pre, bool limit) -> int { - if (pos >= m) { + auto dfs = [&](auto&& dfs, int i, int pre, bool limit) -> int { + if (i < 0) { return 1; } - if (!limit && f[pos][pre] != -1) { - return f[pos][pre]; + if (!limit && f[i][pre] != -1) { + return f[i][pre]; } - int up = limit ? s[pos] - '0' : 1; + int up = limit ? (n >> i & 1) : 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); + for (int j = 0; j <= up; ++j) { + if (j && pre) { + continue; } + ans += dfs(dfs, i - 1, j, limit && j == up); } if (!limit) { - f[pos][pre] = ans; + f[i][pre] = ans; } return ans; }; - return dfs(dfs, 0, 0, true); + return dfs(dfs, m - 1, 0, true); } }; 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 e68031cff719b..aaa7f22916575 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,32 +1,32 @@ func findIntegers(n int) int { - s := strconv.FormatInt(int64(n), 2) - m := len(s) - f := make([][]int, m) + m := bits.Len(uint(n)) + f := make([][2]int, m) for i := range f { - f[i] = []int{-1, -1} + f[i] = [2]int{-1, -1} } - var dfs func(int, int, bool) int - dfs = func(pos int, pre int, limit bool) int { - if pos >= m { + var dfs func(i, pre int, limit bool) int + dfs = func(i, pre int, limit bool) int { + if i < 0 { return 1 } - if !limit && f[pos][pre] != -1 { - return f[pos][pre] + if !limit && f[i][pre] != -1 { + return f[i][pre] } up := 1 if limit { - up = int(s[pos] - '0') + up = n >> i & 1 } ans := 0 - for i := 0; i <= up; i++ { - if !(pre == 1 && i == 1) { - ans += dfs(pos+1, i, limit && i == up) + for j := 0; j <= up; j++ { + if j == 1 && pre == 1 { + continue } + ans += dfs(i-1, j, limit && j == up) } if !limit { - f[pos][pre] = ans + f[i][pre] = ans } return ans } - return dfs(0, 0, true) + return dfs(m-1, 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 62eca73165333..9faca3465fd23 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,29 +1,31 @@ class Solution { - private char[] s; + private int n; private Integer[][] f; public int findIntegers(int n) { - s = Integer.toBinaryString(n).toCharArray(); - f = new Integer[s.length][2]; - return dfs(0, 0, true); + this.n = n; + int m = Integer.SIZE - Integer.numberOfLeadingZeros(n); + f = new Integer[m][2]; + return dfs(m - 1, 0, true); } - private int dfs(int pos, int pre, boolean limit) { - if (pos >= s.length) { + private int dfs(int i, int pre, boolean limit) { + if (i < 0) { return 1; } - if (!limit && f[pos][pre] != null) { - return f[pos][pre]; + if (!limit && f[i][pre] != null) { + return f[i][pre]; } - int up = limit ? s[pos] - '0' : 1; + int up = limit ? (n >> i & 1) : 1; int ans = 0; - for (int i = 0; i <= up; ++i) { - if (!(pre == 1 && i == 1)) { - ans += dfs(pos + 1, i, limit && i == up); + for (int j = 0; j <= up; ++j) { + if (j == 1 && pre == 1) { + continue; } + ans += dfs(i - 1, j, limit && j == up); } if (!limit) { - f[pos][pre] = ans; + f[i][pre] = ans; } return ans; } 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 9553346958036..9d4486df561a8 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,16 +1,15 @@ class Solution: def findIntegers(self, n: int) -> int: @cache - def dfs(pos: int, pre: int, limit: bool) -> int: - if pos == len(s): + def dfs(i: int, pre: int, limit: bool) -> int: + if i < 0: return 1 - up = int(s[pos]) if limit else 1 + up = (n >> i & 1) if limit else 1 ans = 0 - for i in range(up + 1): - if pre == 1 and i == 1: + for j in range(up + 1): + if pre and j: continue - ans += dfs(pos + 1, i, limit and i == up) + ans += dfs(i - 1, j, limit and j == up) return ans - s = bin(n)[2:] - return dfs(0, 0, True) + return dfs(n.bit_length() - 1, 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 index e22bdb39fb1b2..6d981fba57c84 100644 --- 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 @@ -1,27 +1,25 @@ 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) { + const m = n.toString(2).length; + const f: number[][] = Array.from({ length: m }, () => Array(2).fill(-1)); + const dfs = (i: number, pre: number, limit: boolean): number => { + if (i < 0) { return 1; } - if (!limit && f[pos][pre] !== -1) { - return f[pos][pre]; + if (!limit && f[i][pre] !== -1) { + return f[i][pre]; } - const up = limit ? parseInt(s[pos]) : 1; + const up = limit ? (n >> i) & 1 : 1; let ans = 0; - for (let i = 0; i <= up; ++i) { - if (!(pre === 1 && i === 1)) { - ans += dfs(pos + 1, i, limit && i === up); + for (let j = 0; j <= up; ++j) { + if (pre === 1 && j === 1) { + continue; } + ans += dfs(i - 1, j, limit && j === up); } if (!limit) { - f[pos][pre] = ans; + f[i][pre] = ans; } return ans; - } - - return dfs(0, 0, true); + }; + return dfs(m - 1, 0, true); }