1 / 6| 豆包MarsCode AI刷题

113 阅读5分钟

1 / 6 第一题问题描述

在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。现在需要你帮助班长小C快速找到那个拿了独特数字卡片的同学手上的数字是什么。

要求:

  1. 设计一个算法,使其时间复杂度为 O(n),其中 n 是班级的人数。
  2. 尽量减少额外空间的使用,以体现你的算法优化能力。

测试样例

样例1:

输入:cards = [1, 1, 2, 2, 3, 3, 4, 5, 5]
输出:4
解释:拿到数字 4 的同学是唯一一个没有配对的。

样例2:

输入:cards = [0, 1, 0, 1, 2]
输出:2
解释:数字 2 只出现一次,是独特的卡片。

样例3:

输入:cards = [7, 3, 3, 7, 10]
输出:10
解释:10 是班级中唯一一个不重复的数字卡片。

约束条件

  • 1 ≤ cards.length ≤ 1001
  • 0 ≤ cards[i] ≤ 1000
  • 班级人数为奇数
  • 除了一个数字卡片只出现一次外,其余每个数字卡片都恰好出现两次

为了找到那个拿了独特数字卡片的同学手上的数字,我们可以利用异或(XOR)操作的特性。异或操作有一个重要的性质:对于任何整数 xx ^ x = 0,并且 x ^ 0 = x。这意味着如果我们对数组中的所有数字进行异或操作,最终的结果将是那个唯一出现一次的数字。

解题思路

  1. 理解问题:我们需要找到数组中唯一一个出现一次的数字。
  2. 选择数据结构:由于题目要求时间复杂度为 O(n) 且尽量减少额外空间的使用,我们可以使用异或操作。
  3. 算法步骤
    • 初始化一个变量 result 为 0。
    • 遍历数组中的每一个数字,将其与 result 进行异或操作。
    • 最终 result 的值就是那个唯一出现一次的数字。

代码实现

def solution(cards):
    result = 0
    for card in cards:
        result ^= card
    return result

if __name__ == "__main__":
    print(solution([1, 1, 2, 2, 3, 3, 4, 5, 5]) == 4)
    print(solution([0, 1, 0, 1, 2]) == 2)
    print(solution([7, 3, 3, 7, 10]) == 10)

解释

  • result ^= card 表示将 result 与当前的 card 进行异或操作,并将结果赋值给 result
  • 由于异或操作的性质,所有出现两次的数字都会相互抵消,最终 result 中只会留下那个唯一出现一次的数字。

测试样例

  • solution([1, 1, 2, 2, 3, 3, 4, 5, 5]) 返回 4,因为 4 是唯一出现一次的数字。
  • solution([0, 1, 0, 1, 2]) 返回 2,因为 2 是唯一出现一次的数字。
  • solution([7, 3, 3, 7, 10]) 返回 10,因为 10 是唯一出现一次的数字。

这个算法的时间复杂度为 O(n),空间复杂度为 O(1),完全符合题目的要求。

1/ 6 第二题问题描述

小M在工作时遇到了一个问题,他需要将用户输入的不带千分位逗号的数字字符串转换为带千分位逗号的格式,并且保留小数部分。小M还发现,有时候输入的数字字符串前面会有无用的 0,这些也需要精简掉。请你帮助小M编写程序,完成这个任务。


测试样例

样例1:

输入:s = "1294512.12412"
输出:'1,294,512.12412'

样例2:

输入:s = "0000123456789.99"
输出:'123,456,789.99'

样例3:

输入:s = "987654321"
输出:'987,654,321'

问题理解

我们需要将一个不带千分位逗号的数字字符串转换为带千分位逗号的格式,并且保留小数部分。此外,如果输入的数字字符串前面有无效的 0,这些 0 也需要被去除。

数据结构选择

  • 字符串:因为我们需要处理和格式化字符串。

算法步骤

  1. 去除前导零

    • 使用 lstrip('0') 方法去除字符串前面的无效 0
    • 如果去除后字符串为空,说明原字符串全是 0,此时应将字符串设置为 '0'
  2. 分离整数部分和小数部分

    • 检查字符串中是否包含小数点 .
    • 如果包含小数点,使用 split('.') 方法将字符串分割为整数部分和小数部分。
    • 如果不包含小数点,整数部分就是整个字符串,小数部分为空字符串。
  3. 对整数部分添加千分位逗号

    • 从整数部分的末尾开始,每隔三位插入一个逗号。
    • 可以使用 reversed() 函数和 enumerate() 函数来实现这个逻辑。
  4. 合并整数部分和小数部分

    • 如果小数部分不为空,将整数部分和小数部分用小数点连接起来。
    • 如果小数部分为空,直接返回整数部分。

总结

通过以上步骤,我们可以将一个不带千分位逗号的数字字符串转换为带千分位逗号的格式,并且保留小数部分。希望这些思路能帮助你更好地理解和解决这个问题。

代码实现

def solution(s: str) -> str:

    # write code here
    s = s.lstrip('0')
    if s == '':
        s = '0'

    # 分离整数部分和小数部分
    if '.' in s:
        integer_part, fractional_part = s.split('.')
    else:
        integer_part, fractional_part = s, ''

    # 对整数部分添加千分位逗号
    integer_part_with_commas = ''
    for i, char in enumerate(reversed(integer_part)):
        if i > 0 and i % 3 == 0:
            integer_part_with_commas = ',' + integer_part_with_commas
        integer_part_with_commas = char + integer_part_with_commas

    # 合并整数部分和小数部分
    if fractional_part:
        return integer_part_with_commas + '.' + fractional_part
    else:
        return integer_part_with_commas

if __name__ == '__main__':

    print(solution("1294512.12412") == '1,294,512.12412')
    print(solution("0000123456789.99") == '123,456,789.99')
    print(solution("987654321") == '987,654,321')