Java 试图理解从两个排序数组中查找第k个最小值的算法

Java 试图理解从两个排序数组中查找第k个最小值的算法,java,arrays,algorithm,big-o,divide-and-conquer,Java,Arrays,Algorithm,Big O,Divide And Conquer,说明:给定两个排序的数组(无降序),在T=O(lg(m+n))中查找第k个min元素,m和n的长度为2 数组 问题: 不了解以下三点算法: 当A[aPartitionIndex]

说明:
给定两个排序的数组(无降序),在T=O(lg(m+n))中查找第k个min元素,m和n的长度为2 数组

问题:
不了解以下三点算法:

  • 当A[aPartitionIndex]
  • 为什么不能把A的左半部和B的右半部放在一起 同一时间
  • 一些“资源”称该算法可用于寻找第k个最小值 在N个排序数组中,如何?把k分成N部分
代码:Java解决方案:二进制搜索

    // k is based on 1, not 0.
    public int findKthMin(int[] A, int as, int ae, 
                           int[] B, int bs, int be, int k) {

        int aLen = ae - as + 1;
        int bLen = be - bs + 1;

        // Guarantee the first array's size is smaller than the second one,
        // which is convenient to remaining part calculation.
        if (aLen > bLen) return findKthMin(B, bs, be, 
                                           A, as, ae, k);

        // Base case.
        if (aLen == 0) return B[bs + k - 1];
        if (k == 1) return Math.min(A[as], B[bs]); // k based on 1, not 0.

        // Split k, 
        // one part is distributed to A,
        // the other part is distributed to B.
        int ak = aLen < (k/2)? aLen: k/2;
        int bk = k - ak;

        // *k is based on 1, not 0.
        int aPartitionIndex = as + (ak - 1);
        int bPartitionIndex = bs + (bk - 1);

        if (A[aPartitionIndex] == B[bPartitionIndex]) {
            return A[aPartitionIndex];

        } else if (A[aPartitionIndex] < B[bPartitionIndex]) {
            // Drop the left part of A, and
            // do recursion on the right part of A, and
            // the entire current part of B.
            k = k - ak;
            return findKthMin(A, aPartitionIndex + 1, ae, 
                              B, bs, be, k);

        } else {
            // Drop the left part of B, and
            // do recursion on the entire current part of A, and
            // the right part of B.
            k = k - bk;
            return findKthMin(A, as, ae, 
                              B, bPartitionIndex + 1, be, k);
        }
    }
//k基于1,而不是0。
公共金融机构(int[]A、int as、int ae、,
int[]B,int-bs,int-be,int-k){
int aLen=ae-as+1;
int-bLen=be-bs+1;
//保证第一个数组的大小小于第二个数组的大小,
//便于剩余部分的计算。
如果(aLen>bLen)返回findKthMin(B,bs,be,
A、 as,ae,k);
//基本情况。
如果(aLen==0)返回B[bs+k-1];
if(k==1)返回Math.min(A[as],B[bs]);//k基于1,而不是0。
//分裂k,
//一部分分配给一个,
//另一部分分配给B。
int-ak=aLen<(k/2)?aLen:k/2;
int-bk=k-ak;
//*k基于1,而不是0。
int apartionindex=as+(ak-1);
int bPartitionIndex=bs+(bk-1);
如果(A[aPartitionIndex]==B[bPartitionIndex]){
返回[aPartitionIndex];
}如果(A[aPartitionIndex]1)假设
A
B
按升序排序,
A[apartionindex]
意味着
A[i]
适用于所有
i

2) 你永远不能删除数组的正确部分,因为你不知道它们在排序中的位置。

1)假设
A
B
按升序排序,
A[apartionindex]
意味着
A[i]
对于所有
i


2) 您永远不能删除数组的正确部分,因为您不知道它们在排序中的位置。

Hi@Code Peedient,[1]您强调了“升序”,如果我们将此算法应用于包含重复项的数组,是否存在任何问题?[2] 我仍然无法理解“为什么我们可以直接放下A的左边部分”,为什么我们可以确定我们的第k个min不在那一部分,你能给出一些反例吗?我试图找到反例,但找不到。非常感谢你@赵楠重复与升序排序有什么关系?(也许“非降序”在技术上更准确。)嗨@代码学徒,谢谢你的帮助!但严重的问题仍然是,我无法证明为什么我们可以直接删除A的左侧部分,似乎删除A的左侧部分是非常正确的,但我就是找不到为什么?有反例吗?@Zhaonan如果这样做是正确的,那么就不会有反例。另一方面,通过一个示例并使用调试器逐步完成algo肯定会揭示它是如何工作的。你是对的,“如果这样做是正确的,那么就不会有反例”。但我认为“同时删除A的左部分和B的右部分”应该有一些反例,但我无法找到。您好@Code Peedient,[1]您强调了“升序”,如果我们将此算法应用于包含重复项的数组,该算法是否有问题?[2] 我仍然无法理解“为什么我们可以直接放下A的左边部分”,为什么我们可以确定我们的第k个min不在那一部分,你能给出一些反例吗?我试图找到反例,但找不到。非常感谢你@赵楠重复与升序排序有什么关系?(也许“非降序”在技术上更准确。)嗨@代码学徒,谢谢你的帮助!但严重的问题仍然是,我无法证明为什么我们可以直接删除A的左侧部分,似乎删除A的左侧部分是非常正确的,但我就是找不到为什么?有反例吗?@Zhaonan如果这样做是正确的,那么就不会有反例。另一方面,通过一个示例并使用调试器逐步完成algo肯定会揭示它是如何工作的。你是对的,“如果这样做是正确的,那么就不会有反例”。不过,我认为应该有一些反例,例如“同时放下A的左半部和B的右半部”,但我看不出来。