📌  相关文章
📜  不超过 N 且不包含 S 的任何数字的最大数(1)

📅  最后修改于: 2023-12-03 14:48:51.621000             🧑  作者: Mango

题目介绍

给定一个不超过 $N$ 的正整数和一个数字 $S$,找到一个最大的不含 $S$ 的数字。例如,当 $N=100$,$S=4$ 时,最大的不含 $S$ 的数字是 $99$。

算法思路

首先,我们需要将 $N$ 拆分成各个位上的数字,例如 $N=1234$,我们可以拆分成 $1$、$2$、$3$、$4$ 四个数字。接着,我们从最高位开始遍历这些数字,如果当前数字等于 $S$,那么将其减 $1$;如果当前数字小于 $S$,则直接将剩下的数字依次设置为 $9$。最后,将处理完后的数字重新组合,即为最终结果。

举个例子,当 $N=1234567$,$S=5$ 时,我们的处理过程如下:

  1. 将 $N$ 拆分成 $1$、$2$、$3$、$4$、$5$、$6$、$7$ 七个数字。
  2. 从最高位开始遍历,得到当前数字为 $1$,不需要进行处理。
  3. 继续遍历下一个数字,得到当前数字为 $2$,不需要进行处理。
  4. 继续遍历下一个数字,得到当前数字为 $3$,不需要进行处理。
  5. 继续遍历下一个数字,得到当前数字为 $4$,不需要进行处理。
  6. 继续遍历下一个数字,得到当前数字为 $5$,将其减 $1$ 得到 $4$。
  7. 因为我们已经将 $5$ 处理过了,所以剩下的数字都要设置为 $9$,即将 $6$、$7$ 分别设置为 $9$。
  8. 将处理完后的数字重新组合,得到最终结果为 $4999999$。
代码实现

下面是实现上述算法的 Python 代码:

def get_max_num_without_s(n: int, s: int) -> int:
    digits = []
    while n > 0:
        digits.append(n % 10)
        n //= 10
    digits.append(0)  # 加一个哨兵,避免边界问题
    for i in range(len(digits)-1):
        if digits[i] == s:
            digits[i] = 9
            for j in range(i+1, len(digits)-1):
                if digits[j] != s and digits[j] != 9:
                    digits[j] = 9
                else:
                    break
            break
        elif digits[i] < s:
            for j in range(i, len(digits)-1):
                if digits[j] != s:
                    digits[j] = 9
                else:
                    break
            break
    res = 0
    for i in range(len(digits)-2, -1, -1):
        res = res * 10 + digits[i]
    return res

这段代码中,我们将 $N$ 拆分成各个位上的数字,并将这些数字保存在一个列表中。接着,我们从最高位开始遍历这些数字,使用两个循环分别处理当前数字等于 $S$ 和小于 $S$ 的情况。最后,将处理完成后的数字重新组合,得到最终结果。

总结

本题目的思路较为简单,需要注意处理一些边界情况。在实现过程中,我们使用了列表来保存各个位上的数字,因为列表的修改操作比字符串更加高效。此外,我们还使用了哨兵来避免边界问题,这也是一个编程技巧。