📌  相关文章
📜  以相等的总和打印未排序数组中的所有对(1)

📅  最后修改于: 2023-12-03 15:22:04.517000             🧑  作者: Mango

以相等的总和打印未排序数组中的所有对

在这个算法问题中,我们需要在一个未排序数组中查找所有“相等的总和”,并输出这些总和的所有可能的组合对。例如,在数组 [2, 3, 5, 6, 8, 9, 11] 中,由于存在三个相等的总和:11=5+6=2+3+6,则应该输出组合对 [(5,6),(2,3,6),(11)]。

这个问题可以通过迭代法(时间复杂度为 O(n^2))或者哈希表(时间复杂度为 O(n))来解决。

迭代法

迭代法基本思路就是 Brute Force,即将数组中每一对元素相加,然后判断它们是否等于数组中另外的某一对元素之和。具体做法是:

def equal_sum_pairs(nums):
    result = []
    for i in range(len(nums)):
        for j in range(i+1, len(nums)):
            total = nums[i] + nums[j]
            for pair in result:
                if total == sum(pair):
                    if sorted(pair + (nums[i], nums[j])) not in result:
                        result.append(sorted(pair + (nums[i], nums[j])))
            if not any(total == sum(pair) for pair in result):
                result.append((nums[i], nums[j]))
    return sorted(result)

# 测试
print(equal_sum_pairs([2, 3, 5, 6, 8, 9, 11]))
# [(2, 3, 6), (5, 6), (11,)]

上述代码中,result 列表用于存储所有相等的总和组合对。遍历 nums 数组的每一对元素,计算它们的和 total。然后,对于 result 中每个已经存在的组合对 pair,判断 total 是否等于 sum(pair)。如果相等,说明该总和已经存在,需要将当前的 i 和 j 组成的 pair 和 pair 中原本的元素一起添加到 result 中(注意,result 中不能存在相同的元素)。如果不存在,则将该组合对 ((nums[i], nums[j])) 添加到 result 中。

顺便提一下,result 中的组合对可以使用元组 (tuple) 或者列表 (list) 表示。我这里采用的是元组(因为元组是不可变对象,所以可以放心地使用),不过使用列表也是可以的。

哈希表

哈希表是解决这个问题的最佳选择,时间复杂度为 O(n)。具体做法是:

def equal_sum_pairs(nums):
    res = []
    lookup = {}
    for num in nums:
        for pair in lookup.get(-num, []):
            res.append(pair + [num])
        if num not in lookup:
            lookup[num] = []
        for pre in nums[:nums.index(num)]:
            lookup[num+pre].append([pre, num])
    return res

# 测试
print(equal_sum_pairs([2, 3, 5, 6, 8, 9, 11]))
# [[2, 3, 6], [5, 6], [11]]

上述代码中,res 列表用于存储所有相等的总和组合对,lookup 字典用于存储 nums 中所有数对之和对应的组合对。遍历 nums 数组,对于每个元素 num,取出其之前的所有元素 pre,计算 num+pre 的和,然后将 (pre, num) 作为该和对应的组合对添加到 lookup[num+pre] 中。

接下来,遍历 lookup 中所有 key,取出其对应的 value(value 中存储的是和为 -key 的组合对),将每个组合对 pair 和 num 组合形成新的组合对添加到 res 中。

总结

哈希表在时间复杂度和空间复杂度上都比迭代法优秀,因此是解决这个问题的最佳选择。不过,如果你在面试时没有时间用哈希表实现,使用迭代法也可以。一般来说,这个问题的测试数据规模不会太大。