如何在递归分治解决方案中自下而上传递原始数组的索引?

Posted

技术标签:

【中文标题】如何在递归分治解决方案中自下而上传递原始数组的索引?【英文标题】:How to pass a index of the original array from buttom up in a recursive divide-and-conquer solution? 【发布时间】:2020-02-09 10:58:55 【问题描述】:

我正在为硬件问题创建一个分而治之的算法。给定一个数组,我需要找到最大值的索引(如果有多个索引,则为任何索引)。如果我想返回最高值,我的解决方案有效,但是在尝试从堆栈的底部传递索引时发现困难。每个级别的数组大小不同。

    int findLargestPos(int[] arr) 
        int n = arr.length;
        int mid = (int)Math.floor(arr.length / 2);

        if (arr.length <= 1) 
            return 0;
        

        int[] arr2 = new int[mid];
        int[] arr3 = new int[arr.length - mid];

        copyArr(arr, arr2, 0, 0);
        copyArr(arr, arr3, mid, 0);

        int index1 = findLargestPos(arr);
        int index2 = findLargestPos(arr);

        // Problem starts
        if (value from arr2 is greater than arr3) 
            return arr2 index
        

        return arr3 index
    

【问题讨论】:

【参考方案1】:

您可以将偏移量变量传递给findLargestPos 方法,而不是创建一个类来存储索引,它可以告诉您传递给该方法的数组的第一个元素距离第一个元素的右侧有多远从第一个函数调用传入的原始数组。

int findLargestPos(int[] arr, int offset) 
    ...

所以第一次调用findLargestPos时,传递的偏移量应该是0。

findLargestPos(arr, 0)

当进一步递归调用findLargestPos时,传递给左数组的偏移量应该是传递给当前函数调用的偏移量,而传递给右数组的偏移量应该是传递给当前函数调用的偏移量加上mid

int index1 = findLargestPos(arr2, offset); // left array
int index2 = findLargestPos(arr3, offset + mid); // right array

但是,要从原始数组中获取索引,我们还必须更改基本条件。目前,当数组中只剩下一个或更少的元素时,您总是返回0。相反,您应该传递 offset 变量,因为这应该表示原始数组中值的索引。

if (arr.length <= 1) 
    return offset;

现在解决您的主要问题,如何准确比较出现最大值的左右数组的索引处的值。事情是这样的:从对findLargestPos 的函数调用返回的索引表示原始数组中最大值的索引。但是要访问子数组中的这些值,您必须使用偏移变量。例如,假设原始数组被分成两个大小为 3 的数组。如果右子数组中的最大值对应于原始数组中的索引 4,那么它对应于右子数组中的索引 1。由于在这种情况下mid 为 3,我们将从索引中减去偏移量以获得访问正确子数组中的值的适当索引。相同的逻辑适用于左子数组。所以这就是最终方法实现的样子,

public static int findLargestPos(int[] arr, int offset) 
    int n = arr.length;
    int mid = (int)Math.floor(arr.length / 2);

    if (arr.length <= 1) 
        return offset;
    

    int[] arr2 = new int[mid];
    int[] arr3 = new int[arr.length - mid];

    System.arraycopy(arr, 0, arr2, 0, mid);
    System.arraycopy(arr, mid, arr3, 0, arr.length - mid);

    int index1 = findLargestPos(arr2, offset);
    int index2 = findLargestPos(arr3, offset + mid);

    if (arr[index1 - offset] > arr[index2 - offset]) 
        return index1;
    

    return index2;

请注意,我将您对 copyArr 的调用替换为对 System.arraycopy 的调用。

【讨论】:

【参考方案2】:

您将必须创建一个类对象来存储它们以返回,因此创建一个将存储 1 个数组和 1 个整数的类 - 例如:

class ArrayDetails 
 int[] array;
 int index;
 ArrayDetaild(array, index) 
  this.array = array;
  this.index = index;
 

【讨论】:

以上是关于如何在递归分治解决方案中自下而上传递原始数组的索引?的主要内容,如果未能解决你的问题,请参考以下文章

归并排序-marge-sort

如何知道数组中偶数索引值之和与奇数索引值之和之间的差异(递归代码)

分治法解决最大子数组问题

硬件递归分治算法

算法——分治和快速排序

分治思想--快速排序解决TopK问题