📌  相关文章
📜  使得x <y的数组中(x,y)对的计数(1)

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

计数(x,y)对使得x<y的数组

在计算机科学中,计数问题是一个非常基础且重要的问题。给定一个数组,我们需要计算有多少对(x,y)满足x<y。

方法一:暴力法

最简单的方法是使用两个嵌套循环来遍历每一个可能的(x,y)对,判断它们是否满足x<y。这个算法的时间复杂度为O(N^2)。

count = 0
for i in range(len(nums)):
    for j in range(i+1, len(nums)):
        if nums[i] < nums[j]:
            count += 1
return count
方法二:归并排序

我们可以使用归并排序来优化暴力法。在归并排序的过程中,如果左边的元素小于右边的元素,那么左边的元素就会与右边的所有元素匹配。因此我们可以在归并排序的merge函数中加入一个计数器count,用来统计有多少次左边的元素比右边的元素小。

count = 0
def merge(nums, left, mid, right, temp):
    i, j, k = left, mid+1, left
    while i <= mid and j <= right:
        if nums[i] <= nums[j]:
            temp[k] = nums[i]
            i += 1
        else:
            temp[k] = nums[j]
            j += 1
            count += mid - i + 1
        k += 1
    while i <= mid:
        temp[k] = nums[i]
        i += 1
        k += 1
    while j <= right:
        temp[k] = nums[j]
        j += 1
        k += 1
    nums[left:right+1] = temp[left:right+1]

def mergeSort(nums, left, right, temp):
    if left < right:
        mid = (left + right) // 2
        mergeSort(nums, left, mid, temp)
        mergeSort(nums, mid+1, right, temp)
        merge(nums, left, mid, right, temp)

def countPairs(nums):
    global count
    count = 0
    temp = [0] * len(nums)
    mergeSort(nums, 0, len(nums)-1, temp)
    return count

时间复杂度为O(NlogN)。

方法三:树状数组

树状数组是一个非常高效的数据结构,可以在O(logN)的时间复杂度内修改和查询区间和。我们可以使用树状数组来快速计算(x,y)对使得x<y的个数。

首先将数组从小到大排序,遍历数组,对于每一个元素x,用树状数组查询0~x之间的元素个数sum,那么(x,y)对使得x<y的个数就是sum。

def countPairs(nums):
    def lowbit(x):
        return x & (-x)

    n = len(nums)
    sorted_nums = sorted(nums)
    tree = [0] * (n+1)

    def query(x):
        res = 0
        while x > 0:
            res += tree[x]
            x -= lowbit(x)
        return res

    def update(x, val):
        while x <= n:
            tree[x] += val
            x += lowbit(x)

    count = 0
    for i in range(n):
        x = nums[i]
        rank = bisect.bisect_left(sorted_nums, x) + 1
        count += i - query(rank-1)
        update(rank, 1)
    return count

时间复杂度为O(NlogN)。