【问题标题】:Finding smallest element in an integer array in java using divide and conquor algorithm使用分治算法在java中查找整数数组中的最小元素
【发布时间】:2015-07-29 01:22:31
【问题描述】:

我尝试使用我对分治算法的理解来找到整数数组中的最小元素。 我得到了正确的结果。 但我不确定这是否是使用分而治之算法的传统方式。 如果有任何其他比我尝试过的更智能的分治算法实现方法,请告诉我。

public static int smallest(int[] array){
       int i = 0;
       int array1[] = new int[array.length/2];
       int array2[] = new int[array.length - (array.length/2)];
       for(int index = 0; index < array.length/2 ; index++){
               array1[index] = array[index];
        }
        for(int index = array.length/2; index < array.length; index++){
               array2[i] = array[index];
                i++;
        }
        if(array.length > 1){
            if(smallest(array1) < smallest(array2)){
                return smallest(array1);
            }else{
                 return smallest(array2);
              }
        }
        return array[0];
   }

【问题讨论】:

  • 是的,这是实现这种分而治之算法的正确方法。如果您可以尝试在每次调用中不创建新数组,那就更好了。
  • 查看之前的帖子以获得一些想法:stackoverflow.com/questions/14949982/…
  • @karthikthanx。我会按照您的建议尝试。

标签: java


【解决方案1】:

您的代码是正确的,但您可以使用Arrays.copyOfRange 和Math.min 等现有函数编写更少的代码

public static int smallest(int[] array) {
    if (array.length == 1) {
        return array[0];
    } 
    int array1[] = Arrays.copyOfRange(array, 0, array.length / 2);
    int array2[] = Arrays.copyOfRange(array, array.length / 2, array.length);
    return Math.min(smallest(array1), smallest(array2));        
}

还有一点。在开头测试length == 1 是更具可读性的版本。在功能上是相同的。从性能的角度来看,它创建的数组更少,并尽快从smallest 函数中退出。

还可以在不需要创建新数组的情况下使用不同形式的递归。

private static int smallest(int[] array, int from, int to) {
    if (from == to) {
        return array[from];
    }
    int middle = from + (to - from) / 2;
    return Math.min(smallest(array, from, middle), smallest(array, middle + 1, to));
}

public static int smallest(int[] array){
    return smallest(array, 0, array.length - 1);
}

第二个版本效率更高,因为它不会创建新数组。

【讨论】:

  • OP的代码和你的代码有什么区别?
  • 我编辑了答案以表明可以使用现有功能。
【解决方案2】:

我发现在这个特殊的程序中使用分而治之没有任何用处。

无论如何你搜索从 1 到 N 的整个数组,但是分两步

1. 1 to N / 2

2. N / 2 + 1 to N

这相当于 1 到 N。

您还可以在循环之后编写一些额外的检查程序,而这些检查在您直接执行时实际上并不需要。

int min = a[0];
for(int i = 1; i < arr.length; i++)
if(min < a[i])
  a[i] = min;

这被认为是找出最小值的最有效方法。

什么时候使用分而治之

分治算法的工作原理是递归地将一个问题分解为两个或多个子问题,直到这些子问题变得简单到可以直接解决。

考虑合并排序算法。

在这里,我们逐步划分问题,直到我们得到更小的问题,然后我们将它们组合起来进行排序。在这种情况下,这被认为是最佳的。正常运行时间为 O(n * n),而这运行时间为 O(n log n)。

但是在找到最小值时,原始的有 O(n)。所以这很好。

分而治之

书

Data Structures and Algorithm Analysis in Java, 2nd edtition, Mark Allen Weiss

说一个 D&C 算法应该有两个不相交的递归调用。即喜欢快速排序。上面的算法没有这个,即使可以递归实现。

【讨论】:

  • OP正在练习使用分而治之的编程技术,我认为对性能不感兴趣。
  • OP不想写高效的算法,他想测试他对分治范式的理解。所以他的做法是正确的。
  • 纠正 Uma,但我想这只是一个测试,看看分而治之如何运作。但我同意这是这个特定测试的最佳解决方案
【解决方案3】:

您在此处使用代码所做的操作是正确的。但是有更有效的方法来解决这个代码,我相信你已经知道了。

虽然分治算法可以应用于这个问题,但它更适合复杂的数据问题或通过将数据分成更小的片段来理解困难的数据问题。一个典型的例子是'Tower of Hanoi'。

就您的代码而言,它是正确的。这是相同代码的另一个副本-

public class SmallestInteger {

public static void main(String[] args) {
    int small ;
    int array[] = {4,-2,8,3,56,34,67,84} ;
    small = smallest(array) ;
    System.out.println("The smallest integers is = " + small) ;
}

public static int smallest(int[] array) {
    int array1[] = new int[array.length/2];
    int array2[] = new int[array.length - (array.length/2)];

    for (int index = 0; index < array.length/2 ; index++) {
        array1[index] = array[index];
    }
    for (int index = array.length/2; index < array.length; index++) {
        array2[index - array.length/2] = array[index] ;
    }

    if (array.length > 1) {
        if(smallest(array1) < smallest(array2)) {
            return smallest(array1) ;
        }
        else {
            return smallest(array2) ;
        }
    }
    return array[0] ;

}

}

结果出来了-

The smallest integers is = -2

【讨论】:

  • 通过省略另一个变量使第二个“for”循环看起来很漂亮的方式很可爱。
  • 为什么要给smallest打两次电话?您可以通过将其存储在变量中来避免计算时间
猜你喜欢
  • 2012-05-02
  • 1970-01-01
  • 1970-01-01
  • 2017-01-19
  • 2013-05-29
  • 2016-08-16
  • 2018-08-05
  • 2020-01-07
  • 2019-01-12
相关资源
最近更新 更多