四字之字形

ZigZag Quadruples

我看到了这个有趣的问题,想知道是否有更多方法可以解决它:

Given a permutation of numbers from 1 to n, count the number of quadruples indices (i,j,k,l) such that i<j<k<l and A[i]<A[k]<A[j]<A[l]

例如

输入:[1,3,2,6,5,4]
输出:1 (1,3,2,6)

所需的算法是 O(n^2)

方法: 我尝试使用堆栈以类似于 Leetcode 132 pattern 的方式解决它 - 但它似乎失败了。

def get_smaller_before(A):
    smaller_before  = [0] * len(A)
    for i in range(len(A)):
        for j in range(i):
            if A[j] < A[i]:
                smaller_before[i] += 1
    return smaller_before

def get_larger_after(A):
    larger_after = [0] * len(A)
    for i in range(len(A)):
        for j in range(i+1, len(A)):
            if A[i] < A[j]:
                larger_after[i] += 1
    return larger_after

def countQuadrples(nums):
    if not nums:
        return False
    smaller_before      = get_smaller_before(nums)
    larger_after        = get_larger_after(nums)
    counter             = 0
    stack = []
    for j in reversed(range(1, len(nums))):
        # i < j < k < l
        # smaller_before < nums[k] < nums[j] < larger_after
        while stack and nums[stack[-1]] < nums[j]:
            counter += smaller_before[j] * larger_after[stack[-1]]
            stack.pop()
        stack.append(j)
    return counter

有没有人有更好的主意?

你需要的是某种二维树,它可以让你快速回答“k 之后有多少点的值大于 A[j]”的问题,以及“如何j 之前的许多点的值小于 A[k]?”这些通常是 O(n log(n)) 构建的时间,这些查询应该 运行 及时 O(log(n)^2)).

存在许多这样的数据结构。一个选项是 Quadtree 的变体。你把每个数组元素变成一个点,x 坐标是数组中的位置,y 坐标是它的值。你的查询只是计算一个盒子里有多少元素。

现在您可以对所有 j, k 进行双循环,并计算有多少锯齿形四元组将它们作为内部对。