跳转至

1088. 易混淆数 II 🔒

题目描述

易混淆数(Confusing Number)指的是一个数字在整体旋转 180° 以后,能够得到一个和原来 不同 的数,且 新数字的每一位都应该是有效的

本题我们会将数字旋转 180° 来生成一个新的数字。

  • 0、1、6、8、9 旋转 180° 以后,我们得到的新数字分别为 0、1、9、8、6。
  • 当 2、3、4、5、7 旋转 180° 后,是 无法 得到任何数字的。

请注意,在旋转一个数字之后,我们可以忽略前导零。

  • 例如,在旋转 8000 之后,我们有 0008 ,它被认为只是 8

给出正整数 n,请你返回  [1, n] 范围内的 易混淆数 的数量 

 

示例 1:

输入:n = 20
输出:6
解释:易混淆数为 [6,9,10,16,18,19]。
6 转换为 9
9 转换为 6
10 转换为 01 也就是 1
16 转换为 91
18 转换为 81
19 转换为 61

示例 2:

输入:n = 100
输出:19
解释:易混淆数为 [6,9,10,16,18,19,60,61,66,68,80,81,86,89,90,91,98,99,100]。

 

提示:

  • 1 <= n <= 109

解法

方法一:数位 DP

我们先将数字 \(n\) 转成字符串 \(s\)

接下来,我们定义一个函数 \(check(x)\),用来判断 \(x\) 在旋转 \(180^\circ\) 之后是否变成了一个不同的数。如果 \(x\) 在旋转 \(180^\circ\) 之后变成了一个不同的数,那么我们就称 \(x\) 是一个易混淆数。

然后,我们定义另一个函数 \(dfs(pos, limit, x)\),用于搜索从高位到低位的每一位。其中:

  • 参数 \(pos\) 表示当前搜索到的位置,初始时为 \(0\)
  • 参数 \(limit\) 表示当前搜索的数是否受到上界的限制,初始时为 \(true\)
  • 参数 \(x\) 表示当前搜索的数,初始时为 \(0\)

\(dfs(pos, limit, x)\) 中,如果 \(pos \geq len(s)\),那么我们就判断 \(x\) 是否是一个易混淆数,如果是则返回 \(1\),否则返回 \(0\)

否则,我们计算出当前位置上的数字的上界 \(up\),然后枚举当前位置上的数字 \(i\),如果 \(i\) 在旋转 \(180^\circ\) 之后不是一个数字,那么我们就直接跳过这个数字。否则,我们将 \(x\) 更新为 \(x \times 10 + i\),并根据 \(limit\) 的值决定下一步搜索的时候是否受到上界的限制,最后将答案返回。

最终的答案即为 \(dfs(0, true, 0)\)

时间复杂度 \(O(5^{\log_{10}n})\),空间复杂度 \(O(\log_{10}n)\)。其中 \(5^{\log_{10}n}\) 表示 \(n\) 的位数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution:
    def confusingNumberII(self, n: int) -> int:
        def check(x: int) -> bool:
            y, t = 0, x
            while t:
                t, v = divmod(t, 10)
                y = y * 10 + d[v]
            return x != y

        def dfs(pos: int, limit: bool, x: int) -> int:
            if pos >= len(s):
                return int(check(x))
            up = int(s[pos]) if limit else 9
            ans = 0
            for i in range(up + 1):
                if d[i] != -1:
                    ans += dfs(pos + 1, limit and i == up, x * 10 + i)
            return ans

        d = [0, 1, -1, -1, -1, -1, 9, -1, 8, 6]
        s = str(n)
        return dfs(0, True, 0)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
    private final int[] d = {0, 1, -1, -1, -1, -1, 9, -1, 8, 6};
    private String s;

    public int confusingNumberII(int n) {
        s = String.valueOf(n);
        return dfs(0, 1, 0);
    }

    private int dfs(int pos, int limit, int x) {
        if (pos >= s.length()) {
            return check(x) ? 1 : 0;
        }
        int up = limit == 1 ? s.charAt(pos) - '0' : 9;
        int ans = 0;
        for (int i = 0; i <= up; ++i) {
            if (d[i] != -1) {
                ans += dfs(pos + 1, limit == 1 && i == up ? 1 : 0, x * 10 + i);
            }
        }
        return ans;
    }

    private boolean check(int x) {
        int y = 0;
        for (int t = x; t > 0; t /= 10) {
            int v = t % 10;
            y = y * 10 + d[v];
        }
        return x != y;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
public:
    int confusingNumberII(int n) {
        string s = to_string(n);
        int d[10] = {0, 1, -1, -1, -1, -1, 9, -1, 8, 6};
        auto check = [&](int x) -> bool {
            int y = 0;
            for (int t = x; t; t /= 10) {
                int v = t % 10;
                y = y * 10 + d[v];
            }
            return x != y;
        };
        function<int(int, int, int)> dfs = [&](int pos, int limit, int x) -> int {
            if (pos >= s.size()) {
                return check(x);
            }
            int up = limit ? s[pos] - '0' : 9;
            int ans = 0;
            for (int i = 0; i <= up; ++i) {
                if (d[i] != -1) {
                    ans += dfs(pos + 1, limit && i == up, x * 10 + i);
                }
            }
            return ans;
        };
        return dfs(0, 1, 0);
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
func confusingNumberII(n int) int {
    d := [10]int{0, 1, -1, -1, -1, -1, 9, -1, 8, 6}
    s := strconv.Itoa(n)
    check := func(x int) bool {
        y := 0
        for t := x; t > 0; t /= 10 {
            v := t % 10
            y = y*10 + d[v]
        }
        return x != y
    }
    var dfs func(pos int, limit bool, x int) int
    dfs = func(pos int, limit bool, x int) (ans int) {
        if pos >= len(s) {
            if check(x) {
                return 1
            }
            return 0
        }
        up := 9
        if limit {
            up = int(s[pos] - '0')
        }
        for i := 0; i <= up; i++ {
            if d[i] != -1 {
                ans += dfs(pos+1, limit && i == up, x*10+i)
            }
        }
        return
    }
    return dfs(0, true, 0)
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function confusingNumberII(n: number): number {
    const s = n.toString();
    const d: number[] = [0, 1, -1, -1, -1, -1, 9, -1, 8, 6];
    const check = (x: number) => {
        let y = 0;
        for (let t = x; t > 0; t = Math.floor(t / 10)) {
            const v = t % 10;
            y = y * 10 + d[v];
        }
        return x !== y;
    };
    const dfs = (pos: number, limit: boolean, x: number): number => {
        if (pos >= s.length) {
            return check(x) ? 1 : 0;
        }
        const up = limit ? parseInt(s[pos]) : 9;
        let ans = 0;
        for (let i = 0; i <= up; ++i) {
            if (d[i] !== -1) {
                ans += dfs(pos + 1, limit && i === up, x * 10 + i);
            }
        }
        return ans;
    };
    return dfs(0, true, 0);
}

评论

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy