交替数字和

标签: 数学

难度: Easy

给你一个正整数 nn 中的每一位数字都会按下述规则分配一个符号:

  • 最高有效位 上的数字分配到 号。
  • 剩余每位上数字的符号都与其相邻数字相反。

返回所有数字及其对应符号的和。

示例 1:

输入:n = 521
输出:4
解释:(+5) + (-2) + (+1) = 4

示例 2:

输入:n = 111
输出:1
解释:(+1) + (-1) + (+1) = 1

示例 3:

输入:n = 886996
输出:0
解释:(+8) + (-8) + (+6) + (-9) + (+9) + (-6) = 0

提示:

  • 1 <= n <= 109

Submission

运行时间: 20 ms

内存: 16.5 MB

class Solution:
    def alternateDigitSum(self, n: int) -> int:
        for i in range(1, (le_n := len(l_n := list(str(n)))) + 1, 2):
            if i < le_n:
                l_n[i] = '-' + l_n[i]
        return sum(map(lambda x: int(x), l_n))

Explain

此题解首先将整数 n 转换为字符串,然后转换为字符列表,以便对每个数字单独操作。遍历这个列表的奇数位置的索引(从 1 开始,即第二个元素),并在这些位置的数字前添加负号,从而符合题目要求的符号变换。然后,使用 map 函数将修改后的字符串列表中的每个元素转换回整数,并计算它们的总和。这样处理后,最高有效位保持为正,其余位按要求交替变换符号。

时间复杂度: O(d)

空间复杂度: O(d)

class Solution:
    def alternateDigitSum(self, n: int) -> int:
        # 将数字转换为字符列表
        l_n = list(str(n))
        le_n = len(l_n)
        # 从第二位开始,每两位改变一次符号
        for i in range(1, le_n, 2):
            l_n[i] = '-' + l_n[i]
        # 将带符号的字符串列表转换回整数并计算总和
        return sum(map(int, l_n))

Explore

将整数转换为字符串再转换为字符列表允许我们直接访问和操作每个数字的符号。在字符串形式中,每个数字都是独立的字符,便于在不同的位置插入符号或进行其他修改。这种方法简化了数位的直接操作,尤其是在需要对特定位置的数字进行符号变更时。直接在整数上操作每位数字的符号会更复杂,因为涉及到位操作和数位的分离,这在某些编程环境中可能不是直观的。

在题解中,`for i in range(1, le_n, 2)`循环的开始索引是1,这表示循环从字符串的第二个字符开始执行。索引1对应数字的第二位。因此,循环在每个迭代中跳过一位,从第二位开始,然后是第四位,第六位,依此类推,为这些位置的数字前添加负号。由于循环的起始索引是1,最高有效位(即字符串的第一个字符,索引0)不会被循环处理,保持其原符号(通常是正号)。

虽然可以通过使用数学方法直接在整数上操作来解决这个问题,例如通过循环提取每位数字,然后根据其位置确定是添加到总和还是从总和中减去,但这样的方法通常需要更多的数学计算,如使用除法和模运算来不断地分解整数。这种方法虽然可以避免字符串转换的开销,但其代码实现可能更为复杂,而且在可读性和易于调试方面可能不如操作字符串直观。总体来说,直接操作整数的方法可能在执行效率上略有优势,但在实现和维护上可能更复杂。

是的,即使在所有数字都相同的情况下,例如1111,这种方法仍然有效。按照题解的方法,第二位和第四位数字前会添加负号,变成1-1+1-1。这种情况下的结果是0,符合预期的处理逻辑。这个方法是基于数字的位置来添加负号的,而与数字的具体值无关,因此即使是连续相同的数字也能正确处理。