跳转至

728. 自除数

题目描述

自除数 是指可以被它包含的每一位数整除的数。

  • 例如,128 是一个 自除数 ,因为 128 % 1 == 0128 % 2 == 0128 % 8 == 0

自除数 不允许包含 0 。

给定两个整数 left 和 right ,返回一个列表,列表的元素是范围 [left, right](包括两个端点)内所有的 自除数

 

示例 1:

输入:left = 1, right = 22
输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 15, 22]

示例 2:

输入:left = 47, right = 85
输出:[48,55,66,77]

 

提示:

  • 1 <= left <= right <= 104

解法

方法一:模拟

我们定义一个函数 \(\textit{check}(x)\),用来判断 \(x\) 是否是自除数。函数的实现思路如下:

我们用 \(y\) 来记录 \(x\) 的值,然后不断地对 \(y\) 除以 \(10\),直到 \(y\)\(0\)。在这个过程中,我们判断 \(y\) 的末位是否为 \(0\),或者 \(x\) 是否不能被 \(y\) 的末位整除,如果满足这两个条件中的任意一个,那么 \(x\) 就不是自除数,返回 \(\text{false}\)。否则遍历完所有的位数后,返回 \(\text{true}\)

最后,我们遍历区间 \([\textit{left}, \textit{right}]\) 中的所有数,对每个数调用 \(\textit{check}(x)\),如果返回 \(\text{true}\),那么我们就将这个数加入答案数组中。

时间复杂度 \(O(n \times \log_{10} M)\),其中 \(n\) 是区间 \([\textit{left}, \textit{right}]\) 中的元素个数,而 \(M = \textit{right}\),表示区间中的最大值。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class Solution:
    def selfDividingNumbers(self, left: int, right: int) -> List[int]:
        def check(x: int) -> bool:
            y = x
            while y:
                if y % 10 == 0 or x % (y % 10):
                    return False
                y //= 10
            return True

        return [x for x in range(left, right + 1) if check(x)]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
    public List<Integer> selfDividingNumbers(int left, int right) {
        List<Integer> ans = new ArrayList<>();
        for (int x = left; x <= right; ++x) {
            if (check(x)) {
                ans.add(x);
            }
        }
        return ans;
    }

    private boolean check(int x) {
        for (int y = x; y > 0; y /= 10) {
            if (y % 10 == 0 || x % (y % 10) != 0) {
                return false;
            }
        }
        return true;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public:
    vector<int> selfDividingNumbers(int left, int right) {
        auto check = [&](int x) -> bool {
            for (int y = x; y; y /= 10) {
                if (y % 10 == 0 || x % (y % 10)) {
                    return false;
                }
            }
            return true;
        };
        vector<int> ans;
        for (int x = left; x <= right; ++x) {
            if (check(x)) {
                ans.push_back(x);
            }
        }
        return ans;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
func selfDividingNumbers(left int, right int) (ans []int) {
    check := func(x int) bool {
        for y := x; y > 0; y /= 10 {
            if y%10 == 0 || x%(y%10) != 0 {
                return false
            }
        }
        return true
    }
    for x := left; x <= right; x++ {
        if check(x) {
            ans = append(ans, x)
        }
    }
    return
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
function selfDividingNumbers(left: number, right: number): number[] {
    const check = (x: number): boolean => {
        for (let y = x; y; y = Math.floor(y / 10)) {
            if (y % 10 === 0 || x % (y % 10) !== 0) {
                return false;
            }
        }
        return true;
    };
    return Array.from({ length: right - left + 1 }, (_, i) => i + left).filter(check);
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
impl Solution {
    pub fn self_dividing_numbers(left: i32, right: i32) -> Vec<i32> {
        fn check(x: i32) -> bool {
            let mut y = x;
            while y > 0 {
                if y % 10 == 0 || x % (y % 10) != 0 {
                    return false;
                }
                y /= 10;
            }
            true
        }

        (left..=right).filter(|&x| check(x)).collect()
    }
}

评论