【问题标题】:Finding max and min using divide and conquer approach使用分而治之的方法找到最大值和最小值
【发布时间】:2016-06-15 08:52:03
【问题描述】:

我知道这是一个愚蠢的问题,但我根本不明白。 这段代码取自http://somnathkayal.blogspot.in/2012/08/finding-maximum-and-minimum-using.html

public int[] maxMin(int[] a,int i,int j,int max,int min) {
    int mid,max1,min1;
    int result[] = new int[2];

    //Small(P)
    if (i==j) max = min = a[i];
    else if (i==j-1) { // Another case of Small(P)
        if (a[i] < a[j]) {
            this.max = getMax(this.max,a[j]);
            this.min = getMin(this.min,a[i]); 
        }
        else {
            this.max = getMax(this.max,a[i]); 
            this.min = getMin(this.min,a[j]); }
        } else {
            // if P is not small, divide P into sub-problems.
            // Find where to split the set.

            mid = (i + j) / 2;
            // Solve the sub-problems.
            max1 = min1 = a[mid+1];
            maxMin( a, i, mid, max, min );    
            maxMin( a, mid+1, j, max1, min1 );

            // Combine the solutions.
            if (this.max < max1) this.max = max1;
            if (this.min > min1) this.min = min1;
        }

        result[0] = this.max;
        result[1] = this.min;
        return result;
    }
}

假设数组是 8,5,3,7,我们必须找到最大值和最小值, max和min的初始值=arr[0]=8; 第一次名单将分为8,5 我们用 max=8 和 min=8 调用 MaxMin,因为 i==j-1,我们会得到 max=8,min=5,

下次列表会分为[3,7], min1=max1=arr[mid+1]=3, 我们用 max=3 和 min=3 调用 MaxMin。由于 i 等于 j-1,我们将得到 max=7,min=3,

接下来在 max1,max 和 min1,min 之间进行比较, 这是我的困惑, 这里的 max 和 max1 的值分别是 8 和 7,但是如何? 我们没有在任何地方修改 max1,那么它的值是 7,

根据我的理解,我们调用了 MaxMin,max=3 和 min=3,然后更新了 max=7 和 min=3,但是我们没有返回这些更新的值,那么 max1 和 min1 的值是如何更新的, 我被困在这里,请解释一下。 谢谢。

【问题讨论】:

  • 调用 this.mix 和 this.max 时是否有外部最小值和最大值?
  • @Lordofdark-这是代码somnathkayal.blogspot.in/2012/08/…的链接
  • 我不会称这段代码为“分而治之”——从理论上讲,它相当于一个 for 循环,但在实际效率方面更差(额外的函数调用),并且更加冗长。它确实细分了问题,但与明显的替代方案相比,它征服的很少。二分搜索、Karatsuba、FFT - 是更好的例子。

标签: java arrays max min divide-and-conquer


【解决方案1】:

看起来您正在更新 2 个外部值(不在此函数中),即 this.min 和 this.max

您所做的只是分割成 1 或 2 个元素,然后更新 this.min 和 this.max,因此您也可以直接扫描数组并检查所有 int 值的 min/max。这并不是真正的分而治之。

这是一个真正使用分而治之的解决方案:

public int[] maxMin(int[] a,int i,int j) {
    int localmin,localmax;
    int mid,max1,min1,max2,min2;
    int[] result = new int[2];

    //Small(P) when P is one element
    if (i==j) {
        localmin = a[i]
        localmax = a[i];
    }
    else {
        // if P is not small, divide P into sub-problems.
        // where to split the set
        mid = (i + j) / 2;
        // Solve the sub-problems.
        int[] result1 = maxMin( a, i, mid);    
        int[] result2 = maxMin( a, mid+1, j);
        max1 = result1[0];
        min1 = result1[1];
        max2=result2[0];
        min2=result2[1];
        // Combine the solutions.
        if (max1 < max2) localmax = max2;
        else localmax=max1;
        if (min1 < min2) localmin = min1;
        else localmin=min2;
    }

    result[0] = localmax;
    result[1] = localmin;
    return result;
}

【讨论】:

  • 对原始博主的代码进行了很好的改进!我知道您从原始代码继承了它,但我不相信需要“另一种情况的 Small(P)”代码。在我看来,细分代码可以很好地处理这种情况(为了清楚起见,成本是另外两个函数调用。)
  • @Lordofdark-谢谢哥们!!!这段代码有道理,博主的代码完全把我弄糊涂了。
【解决方案2】:

坦率地说,博主的代码看起来一团糟。你应该对它没有信心。

早点看这条线:

if (i==j) max = min = a[i];

传递给函数的值 max 和 min 在这种情况下从未使用过,它们只是被设置,然后永远丢失。另请注意,如果此行运行,则数组 result 既没有设置也没有返回。 (我原以为编译器会警告有些代码路径不返回值。)所以这是一个错误,但由于他从不在任何可能无害的地方使用返回值。

代码有时表现为通过maxmin 返回值(不能这样做),而代码的其他部分则传回数组result,或设置this.max 和@987654327 @。

如果算法会返回错误的结果,我无法在不运行它的情况下做出决定。它可能只是碰巧起作用。但它一团糟,如果它写得更好,你可以自信地看到它是如何工作的。我认为作者应该以更纯粹的函数风格编写它,不依赖this.minthis.max等外部变量。

顺便说一句,我注意到当有人在 cmets 中提出问题时,他的回答是理解算法是主要目标。 “这个算法的实现非常复杂。为了你,我正在用这个更新一个程序。”哎呀,谢谢。

简而言之,找一个不同的例子来研究。黑暗之王在我最初写这篇文章时发布了一个回复,看起来改进了很多。

【讨论】:

    【解决方案3】:

    代码

    import java.util.Random;
    
    public class MinMaxArray {
        
        private static Random R = new Random();
    
        public static void main(String[] args){
        
            System.out.print("\nPress any key to continue.. ");
            try{
                System.in.read();
            }  
            catch(Exception e){
                ;
            }
    
            int N = R.nextInt(10)+5;
            int[] A = new int[N];
    
            for(int i=0; i<N; i++){
                int VAL = R.nextInt(200)-100;
                A[i] = VAL;
            }
    
            Print(A);
    
            Pair P = new Pair(Integer.MIN_VALUE, Integer.MAX_VALUE);
            P = MinMax(A, 0, A.length-1);
    
            System.out.println("\nMin: " + P.MIN);
            System.out.println("\nMax: " + P.MAX);
            
        }
    
        private static Pair MinMax(int[] A, int start, int end) {
            Pair P = new Pair(Integer.MIN_VALUE, Integer.MAX_VALUE);
            Pair P_ = new Pair(Integer.MIN_VALUE, Integer.MAX_VALUE);
            Pair F = new Pair(Integer.MIN_VALUE, Integer.MAX_VALUE);
    
            if(start == end){
                P.MIN = A[start];
                P.MAX = A[start];
    
                return P;
            }
    
            else if(start + 1 == end){
                if(A[start] > A[end]){
                    P.MAX = A[start];
                    P.MIN = A[end];
                }
                else{
                    P.MAX = A[end];
                    P.MIN = A[start];
                }
    
                return P;
            }
    
            else{
                int mid = (start + (end - start)/2);
                P = MinMax(A, start, mid);
                P_ = MinMax(A, (mid + 1), end);
    
                if(P.MAX > P_.MAX){
                    F.MAX = P.MAX;
                }
                else{
                    F.MAX = P_.MAX;
                }
    
                if(P.MIN < P_.MIN){
                    F.MIN = P.MIN;
                }
                else{
                    F.MIN = P_.MIN;
                }
    
                return F;
            }
        }
    
        private static void Print(int[] A) {
            System.out.println();
            for(int x: A){
                System.out.print(x + " ");
            }
            System.out.println();
        }
    }
    
    class Pair{
    
        public int MIN, MAX;
    
        public Pair(int MIN, int MAX){
            this.MIN = MIN;
            this.MAX = MAX;
        }
    }
    
    

    说明

    这是在 Pair 类的帮助下使用 Divide & Conquer approach 找出数组中的 MIN 和 MAX 值的 JAVA 代码。

    Random class of JAVA 使用随机大小 N ε(5, 15) 和范围在 (-100, 100) 之间的随机值初始化 Array。

    创建了一个 Pair 类的对象 P,它从 MinMax() 方法中取回返回值。 MinMax() 方法接受一个数组 (A[])、一个起始索引 (start) 和一个最终索引 (end) 作为参数。


    工作逻辑

    创建了 Pair 类的三个不同对象 P、P_、F。

    案例:-

    1. Array Size -> 1 (start == end) : 在这种情况下, MIN 和 MAX 值都是 A[0],然后将其分配给 Pair 类的对象 P 作为 P.MIN 和 P .MAX,然后返回。

    2. Array Size -> 2 (start + 1 == end) :在这种情况下,代码块比较 Array 的两个值,然后将其分配给 Pair 类的对象 P 作为 P.MIN 和 P。 MAX,然后返回。

    3. Array Size > 2 :在这种情况下,Mid is calculated 和 MinMax 方法从 start -> mid 和 (mid + 1) -> end 调用。它将再次递归调用,直到前两种情况发生并返回值。这些值存储在对象 P 和 P_ 中,然后进行比较,最后由对象 F 作为 F.MAX 和 F.MIN 返回。

    Pair 类有一个同名的方法 Pair(),它接受 2 个 Int 参数,分别为 MIN 和 MAX,然后分配给 Pair.MIN 和 Pair.MAX


    更多代码链接

    https://www.techiedelight.com/find-minimum-maximum-element-array-minimum-comparisons/ https://www.enjoyalgorithms.com/blog/find-the-minimum-and-maximum-value-in-an-array


    【讨论】:

      猜你喜欢
      • 2020-03-30
      • 1970-01-01
      • 2017-02-17
      • 2018-11-09
      • 1970-01-01
      • 2012-05-05
      • 2015-12-31
      • 1970-01-01
      • 2016-02-04
      相关资源
      最近更新 更多