comments | difficulty | edit_url | tags | |||
---|---|---|---|---|---|---|
true |
Hard |
|
Given an integer n
, count the total number of digit 1
appearing in all non-negative integers less than or equal to n
.
Example 1:
Input: n = 13 Output: 6
Example 2:
Input: n = 0 Output: 0
Constraints:
0 <= n <= 109
This problem essentially asks for the number of times the digit
For the range
However, for this problem, we only need to find the value for the range
Here, we use memoized search to implement Digit DP. We search from the starting point downwards, and at the lowest level, we get the number of solutions. We then return the answers layer by layer upwards, and finally get the final answer from the starting point of the search.
The basic steps are as follows:
First, we convert the number
- The digit
$i$ represents the current position being searched, starting from the highest digit, i.e.,$i = 0$ represents the highest digit. - The digit
$\textit{cnt}$ represents the current count of the digit$1$ in the number. - The boolean
$\textit{limit}$ indicates whether the current number is restricted by the upper bound.
The function executes as follows:
If
- If
$j$ equals$1$ , we increment$cnt$ by one. - Recursively call
$\textit{dfs}(i + 1, \textit{cnt}, \textit{limit} \land j = up)$ .
The answer is
The time complexity is
Similar Problems:
Here is the translation of the similar problems into English:
- 357. Count Numbers with Unique Digits
- 600. Non-negative Integers without Consecutive Ones
- 788. Rotated Digits
- 902. Numbers At Most N Given Digit Set
- 1012. Numbers with Repeated Digits
- 2376. Count Special Integers
class Solution:
def countDigitOne(self, n: int) -> int:
@cache
def dfs(i: int, cnt: int, limit: bool) -> int:
if i >= len(s):
return cnt
up = int(s[i]) if limit else 9
ans = 0
for j in range(up + 1):
ans += dfs(i + 1, cnt + (j == 1), limit and j == up)
return ans
s = str(n)
return dfs(0, 0, True)
class Solution {
private int m;
private char[] s;
private Integer[][] f;
public int countDigitOne(int n) {
s = String.valueOf(n).toCharArray();
m = s.length;
f = new Integer[m][m];
return dfs(0, 0, true);
}
private int dfs(int i, int cnt, boolean limit) {
if (i >= m) {
return cnt;
}
if (!limit && f[i][cnt] != null) {
return f[i][cnt];
}
int up = limit ? s[i] - '0' : 9;
int ans = 0;
for (int j = 0; j <= up; ++j) {
ans += dfs(i + 1, cnt + (j == 1 ? 1 : 0), limit && j == up);
}
if (!limit) {
f[i][cnt] = ans;
}
return ans;
}
}
class Solution {
public:
int countDigitOne(int n) {
string s = to_string(n);
int m = s.size();
int f[m][m];
memset(f, -1, sizeof(f));
auto dfs = [&](auto&& dfs, int i, int cnt, bool limit) -> int {
if (i >= m) {
return cnt;
}
if (!limit && f[i][cnt] != -1) {
return f[i][cnt];
}
int up = limit ? s[i] - '0' : 9;
int ans = 0;
for (int j = 0; j <= up; ++j) {
ans += dfs(dfs, i + 1, cnt + (j == 1), limit && j == up);
}
if (!limit) {
f[i][cnt] = ans;
}
return ans;
};
return dfs(dfs, 0, 0, true);
}
};
func countDigitOne(n int) int {
s := strconv.Itoa(n)
m := len(s)
f := make([][]int, m)
for i := range f {
f[i] = make([]int, m)
for j := range f[i] {
f[i][j] = -1
}
}
var dfs func(i, cnt int, limit bool) int
dfs = func(i, cnt int, limit bool) int {
if i >= m {
return cnt
}
if !limit && f[i][cnt] != -1 {
return f[i][cnt]
}
up := 9
if limit {
up = int(s[i] - '0')
}
ans := 0
for j := 0; j <= up; j++ {
t := 0
if j == 1 {
t = 1
}
ans += dfs(i+1, cnt+t, limit && j == up)
}
if !limit {
f[i][cnt] = ans
}
return ans
}
return dfs(0, 0, true)
}
function countDigitOne(n: number): number {
const s = n.toString();
const m = s.length;
const f: number[][] = Array.from({ length: m }, () => Array(m).fill(-1));
const dfs = (i: number, cnt: number, limit: boolean): number => {
if (i >= m) {
return cnt;
}
if (!limit && f[i][cnt] !== -1) {
return f[i][cnt];
}
const up = limit ? +s[i] : 9;
let ans = 0;
for (let j = 0; j <= up; ++j) {
ans += dfs(i + 1, cnt + (j === 1 ? 1 : 0), limit && j === up);
}
if (!limit) {
f[i][cnt] = ans;
}
return ans;
};
return dfs(0, 0, true);
}
public class Solution {
private int m;
private char[] s;
private int?[,] f;
public int CountDigitOne(int n) {
s = n.ToString().ToCharArray();
m = s.Length;
f = new int?[m, m];
return Dfs(0, 0, true);
}
private int Dfs(int i, int cnt, bool limit) {
if (i >= m) {
return cnt;
}
if (!limit && f[i, cnt] != null) {
return f[i, cnt].Value;
}
int up = limit ? s[i] - '0' : 9;
int ans = 0;
for (int j = 0; j <= up; ++j) {
ans += Dfs(i + 1, cnt + (j == 1 ? 1 : 0), limit && j == up);
}
if (!limit) {
f[i, cnt] = ans;
}
return ans;
}
}