如何用O(nlogn)或O(n)的时间复杂度在python中解决对和问题?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何用O(nlogn)或O(n)的时间复杂度在python中解决对和问题?相关的知识,希望对你有一定的参考价值。

阵列中的对和给定一个随机整数数组A和一个数字x。查找并打印数组中总计为x的一对元素。数组A可以包含重复的元素。打印一对时,请先打印较小的元素。也就是说,如果有效对为(6,5),则打印“ 5 6”。没有限制,必须在第一行中打印出5对。您可以按任何顺序打印对,只需注意成对元素的顺序即可。

输入格式:第1行:整数N(数组大小)第2行:数组元素(以空格分隔)第3行:整数x

输出格式:第1行:成对1元素(以空格分隔)第2行:成对2个元素(以空格分隔)第3行:依此类推

约束:1 <= N <= 10001 <= x <= 100

样本输入:

9
1 3 6 2 5 4 3 2 4
7

样本输出:

(1 6)
(3 4)
(3 4)
(2 5)
(2 5)
(3 4)
(3 4)

我的方法::1.Take 2指针/标记的开始和结束分别指向数组的第一个和最后一个元素:2.对数组-o(nlogn)排序3.开始时

代码:

def pairSum(arr, x):
    arr.sort()  # nlogn
    i = 0
    j = len(arr) - 1

    while i < j:
        if arr[i] + arr[j] > x:
            j -= 1

        elif arr[i] + arr[j] < x:
            i += 1

        else:  # got the match  arr[i] +arr[j] ==x
            if arr[i] <= arr[j]:
                print(arr[i], arr[j])

                if arr[j - 1] == arr[j]:
                    j -= 1

                elif arr[i + 1] == arr[i]:
                    i += 1
                else:
                   i += 1
                   j -= 1

            else:
                print(arr[j], arr[i])
                if arr[i + 1] == arr[i]:
                    i += 1
                elif arr[j - 1] == arr[j]:
                    j -= 1
                else:
                    i += 1
                    j -= 1

我已经尝试过这个问题,并且它对于唯一元素运行良好,但是对于重复元素则失败,这是因为while循环会尽早终止。请分享您的想法:)

答案

第一:对数组进行排序并获得while i < j:后,这意味着在第一个else:中条件if arr[i] <= arr[j]:始终为真,因此我将其简化。

第二:您的问题是当您有arr[i + 1] == arr[i]arr[j - 1] == arr[j]时。在这种情况下,在您的实现中,您将减小j值,从而导致一对丢失,因此我将为此条件创建一个if。

可能的更正:

#...
        else:  # got the match  arr[i] +arr[j] ==x
            print(arr[i], arr[j])

            if arr[j - 1] == arr[j] and arr[i + 1] == arr[i]:
                print(arr[i], arr[j])
                print(arr[i], arr[j])
                i += 1
                j -= 1

            elif arr[j - 1] == arr[j]:
                j -= 1

            elif arr[i + 1] == arr[i]:
                i += 1

            else:
                i += 1
                j -= 1
另一答案

对于O(n)复杂度,您可以使用字典来收集与匹配总和(即target-n)相对应的数字,并在遍历列表时直接访问它:

numbers = [1, 3, 6, 2, 5, 4, 3, 2, 4]
target  = 7

matches = dict()
for n in numbers:
    for m in matches.get(n,[]):
        print(f"{n} {m}" if n<m else f"{m} {n}")
    matches.setdefault(target-n,[]).append(n)

输出:

1 6
2 5
3 4
3 4
2 5
3 4
3 4

请注意,当列表中有重复项时,实际上不可能完全达到O(n),因为要打印的结果数可能成指数增长> n

以上是关于如何用O(nlogn)或O(n)的时间复杂度在python中解决对和问题?的主要内容,如果未能解决你的问题,请参考以下文章

O(1), O(n), O(logn), O(nlogn) 的区别

我如何准确识别O(nlogn)?

九大排序算法时间复杂度空间复杂度稳定性

在 O(nlogn) 时间复杂度中找到总和为 0 的子数组(使用分而治之)?

o, o(n), o(logn), o(nlogn)算法复杂度

o, o(n), o(logn), o(nlogn)