Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 将整数数组划分为K个组,使每个组的范围最小_Algorithm_Partitioning - Fatal编程技术网

Algorithm 将整数数组划分为K个组,使每个组的范围最小

Algorithm 将整数数组划分为K个组,使每个组的范围最小,algorithm,partitioning,Algorithm,Partitioning,所以,更正式地说,我得到了N个数字,需要把它们分成K个组,这些组中没有一个是空的。每个组的范围总和必须最小。例如: N=4,K=2,输入为{5,3,1,1} 一种可能的解决方案是{5,3},{1,1}。范围之和为2((5-3)+(1-1)) 另一种方法是{1,1,3}{5},它也是2((3-1)+(单个数字的范围是0)) 范围始终是组中最大数字与组中最小数字之间的差值 当我在互联网上搜索时,很明显我需要使用动态规划,但我得到的只是K=2的解决方案 有人能帮忙吗 对数组进行排序 设am为数组的第m

所以,更正式地说,我得到了N个数字,需要把它们分成K个组,这些组中没有一个是空的。每个组的范围总和必须最小。例如:

N=4,K=2,输入为{5,3,1,1}

一种可能的解决方案是{5,3},{1,1}。范围之和为2((5-3)+(1-1))

另一种方法是{1,1,3}{5},它也是2((3-1)+(单个数字的范围是0))

范围始终是组中最大数字与组中最小数字之间的差值

当我在互联网上搜索时,很明显我需要使用动态规划,但我得到的只是K=2的解决方案

有人能帮忙吗

  • 对数组进行排序
  • 设am为数组的第m个元素;然后,让am=am–am–1∀M∈ [1;N).减法循环必须向后运行,以避免更改am–1.a0≡ 0
  • 对结果数组进行排序,使元素的初始索引与元素本身的排序顺序相同
  • 以最后的K–1索引为例:这些索引加上0,是搜索到的组的第一个元素的索引

  • 使用动态编程,您为k=2找到了一个解决方案。现在考虑如何将其扩展到k=3


    假设f2(n)返回k=2和前n个数字的最优解,f3(n)=f2(n-m)+err(n-m,n)。这是扩展它的一种方法。

    假设数据已排序,则可以在线性时间内执行此操作

    您可以在
    min\u value
    max\u value
    之间的轴上查看数据。简单地说,智能解决方案不使用非连续组,因此任何智能解决方案都可以表示为轴上的一组
    K
    段,每个段
    [x1,x2]
    表示数据中
    x1
    x2
    之间的所有数字

    解决方案的总成本是所有段长度的总和,也是
    max\u value-min\u value-(所有段之间的空间)
    。段之间的空间本身由
    K-1
    空段组成,即没有输入数字,即两个连续输入数字之间的段。您需要的是使
    K-1
    这些段的长度之和最大化

    因此,您所要做的就是(简单版本):

    • 如有必要,对输入进行排序
    • 计算所有i的B[i]=A[i+1]-A[i](A是排序后的输入数组)
    • 检索B的K-1最大值(仍然是线性时间,实际上可以与上一步同时进行)
    • 这些是您的组的边界,因此您可以再次迭代以创建组本身(现在您有了边界)(此步骤也可以与前面的步骤一起完成)
    如果不同值的数量大于K,则所有组都必须为非空。如果不是,则可以轻松拆分包含相同值的重复项的组,使所有组都为非空

    复杂度(如果已经排序):O(n*k)(最多),如果k为常数,则为O(n)。如果不是,则只需改进对最佳k-1段的搜索,最多得到O(n log(n))


    如前所述,额外的内存复杂度很容易达到O(K)

    ,因此在这个问题中,我们希望最小化组的范围

    假设我们有array
    A={1,3,5,7,5,2}

    每个数组中的最大范围为
    max[a]-min[a]
    ,最小范围为
    0

    我们可以使用二进制搜索的一种变体来寻找最小范围,这个答案是有限制的,即组必须包含连续数

    对于二进制搜索,我们需要选择由数组的最小和最大范围给出的边界

    这个psuedo/java代码看起来像这样

    main(){
      int upper = max(A)-min(A); 
      int lower = 0;  
    
    
      while (true) {
        int mid =  upper-lower;  
        int blocks = calculateBlockCount(A, mid); 
        if (blocks < K) {
          upper = mid - 1;
        } 
        else if (blocks > K) {
          lower = mid + 1;
        } 
        else {
          return upper;
          break;
        }
      }
     }
    
        private static int calculateBlockCount(int[] array, int range) {
          int count = 0;
          int[] dumie_array;
          int dumie_array[].add[array[0]];
    
          for (int i = 0; i < array.length; i++) {
            int dumie_array[].add[array[i]]
             if (Func_range(dumie_array) > range) {
               count++;
               dumie_array = array[i];
             } 
             else {
               dumie_array.add(array[i]);
             }
          }
          return count;
        }
    
        private static int Func_range(int[] input) {
           int range = 0;
           range= max(input)-min(input)
           return sum;
         }
    
    main(){
    int上限=最大值(A)-最小值(A);
    整数下限=0;
    while(true){
    int mid=上下;
    int blocks=calculateBlockCount(A,mid);
    if(块K){
    下=中+1;
    } 
    否则{
    返回上;
    打破
    }
    }
    }
    私有静态int calculateBlockCount(int[]数组,int范围){
    整数计数=0;
    int[]dumie_数组;
    int dumie_数组[]。添加[array[0]];
    for(int i=0;i范围){
    计数++;
    dumie_数组=数组[i];
    } 
    否则{
    添加(数组[i]);
    }
    }
    返回计数;
    }
    私有静态int Func_范围(int[]输入){
    int范围=0;
    范围=最大(输入)-最小(输入)
    回报金额;
    }
    
    希望仍然有帮助

    <>我认为大部分都是用java编写的,只有C++没有的添加功能。(不想通过编写数组来写这么多)但是我认为程序的思想应该是清晰的。 这都是基于这篇文章 . 这是一个非常相似的问题

    干杯,
    Gijs

    这些组是否需要包含连续的数字?并且@Koekje he需要将其划分为k个组,并且有N个数字,如果数组已经排序,并且k很小,您将得到复杂性O(N*log(N)),但是您可以通过在减法
    O(N)后不进行排序而找到k-1最佳索引来得到O(N)
    即使排序是不可避免的,也可以保持不变。例如,就地MSR基数排序。如果所有数组元素的大小与
    n
    无关(例如32位),则此算法是严格线性的。