问题1描述:
在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。现在需要你帮助班长小C快速找到那个拿了独特数字卡片的同学手上的数字是什么。
要求:
设计一个算法,使其时间复杂度为 O(n),其中 n 是班级的人数。 尽量减少额外空间的使用,以体现你的算法优化能力。
解题思路
要解决这个问题,我们可以利用异或(XOR)运算的特性。 而异或运算的几个特性:
- 交换律:
a ^ b = b ^ a - 结合律:
a ^ (b ^ c) = (a ^ b) ^ c - 自反性:
a ^ a = 0 - 和零元素异或:
a ^ 0 = a
具体的算法步骤
- 初始化
result = 0; - 遍历数组
cards,对每个元素card执行result = result ^ card; - 遍历结束后,
result则是唯一出现一次的数字。
代码如下:
def solution(cards):
# 进行初始化
result = 0
# 遍历cards数组中的每一个元素
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)
上述python代码的时间和空间复杂度如下:
- 时间复杂度:O(n),只需遍历一次数组。
- 空间复杂度:O(1),只使用了一个额外的变量
result。
此代码可以在不使用额外空间的情况下,以线性时间复杂度找到唯一出现一次的数字。
收获和感想:
只用了一个循环和一个变量就解决了这个问题,算法的高效性较好,并且通过了解异或运算的特性,有效避免了数据结构的额外使用,节省了空间。在下次遇到类似问题时也会去多关注运算特性,从而达到提高算法高效性的目的。
问题2描述:
小R从班级中抽取了一些同学,每位同学都会给出一个数字。已知在这些数字中,某个数字的出现次数超过了数字总数的一半。现在需要你帮助小R找到这个数字。
解题思路
要解决这个问题,可以使用一种称为“摩尔投票算法”的方法。这个算法非常适合用于找出数组中出现次数超过一半的元素。
明确问题: 我们需要找到数组中出现次数超过一半的元素,则说明这个元素的出现次数比其他所有元素的出现次数之和还要多。
具体的算法步骤:
初始化两个变量:candidate 用于存储候选元素,count 用于计数;
遍历数组中的每个元素:
如果 count 为 0,将当前元素设为 candidate,并将 count 设为 1;
如果当前元素与 candidate 相同,count+1;
如果当前元素与 candidate 不同,则count-1;
最终,candidate 就是符合题意寻找的目标元素。
代码如下:
def solution(array):
# 初始化候选的元素和计数器
candidate = None
count = 0
# 遍历数组中的每个元素
for num in array:
# 如果计数器为0,更新候选的元素
if count == 0:
candidate = num
count = 1
# 若当前元素与候选的元素相同,增加计数器count
elif num == candidate:
count += 1
# 若当前元素与候选的元素不同,则减少计数器count
else:
count -= 1
# 返回候选的元素
return candidate
if __name__ == "__main__":
# 添加测试用例
print(solution([1, 3, 8, 2, 3, 1, 3, 3, 3]) == 3)
print(solution([5, 5, 5, 1, 2, 5, 5]) == 5)
print(solution([9, 9, 9, 9, 8, 9, 8, 8]) == 9)
收获和感想:
通过AI提到了“摩尔投票算法”给了解题思路,因为它能够在一次遍历中找到出现次数超过一半的元素。使用了两个变量 candidate 和 count 来跟踪候选的元素和作为计数器,并且在遍历数组时对这两个变量进行更新从而最终实现找到这个元素的目的。