搜寻最小大数的算法需要说明 [英] Need explanation for algorithm searching minimal large sum

查看:77
本文介绍了搜寻最小大数的算法需要说明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实践中解决Codility问题,但无法回答其中一个问题.我在Internet上找到了答案,但是我不知道该算法的工作原理.有人可以一步一步地指导我吗? 这是问题:

I'm solving Codility questions as practice and couldn't answer one of the questions. I found the answer on the Internet but I don't get how this algorithm works. Could someone walk me through it step-by-step? Here is the question:

 /*
  You are given integers K, M and a non-empty zero-indexed array A consisting of N integers.
  Every element of the array is not greater than M.
    You should divide this array into K blocks of consecutive elements.
    The size of the block is any integer between 0 and N. Every element of the array should belong to some block.
    The sum of the block from X to Y equals A[X] + A[X + 1] + ... + A[Y]. The sum of empty block equals 0.
    The large sum is the maximal sum of any block.
    For example, you are given integers K = 3, M = 5 and array A such that:
      A[0] = 2
      A[1] = 1
      A[2] = 5
      A[3] = 1
      A[4] = 2
      A[5] = 2
      A[6] = 2
    The array can be divided, for example, into the following blocks:
    [2, 1, 5, 1, 2, 2, 2], [], [] with a large sum of 15;
    [2], [1, 5, 1, 2], [2, 2] with a large sum of 9;
    [2, 1, 5], [], [1, 2, 2, 2] with a large sum of 8;
    [2, 1], [5, 1], [2, 2, 2] with a large sum of 6.
    The goal is to minimize the large sum. In the above example, 6 is the minimal large sum.
    Write a function:
    class Solution { public int solution(int K, int M, int[] A); }
    that, given integers K, M and a non-empty zero-indexed array A consisting of N integers, returns the minimal large sum.
    For example, given K = 3, M = 5 and array A such that:
      A[0] = 2
      A[1] = 1
      A[2] = 5
      A[3] = 1
      A[4] = 2
      A[5] = 2
      A[6] = 2
    the function should return 6, as explained above. Assume that:
    N and K are integers within the range [1..100,000];
    M is an integer within the range [0..10,000];
    each element of array A is an integer within the range [0..M].
    Complexity:
    expected worst-case time complexity is O(N*log(N+M));
    expected worst-case space complexity is O(1), beyond input storage (not counting the storage required for input arguments).
    Elements of input arrays can be modified.
 */

这是我找到的解决方案,其中包含我不了解的零件的评论:

And here is the solution I found with my comments about parts which I don't understand:

      public static int solution(int K, int M, int[] A) {
    int lower = max(A);  // why lower is max?
    int upper = sum(A);  // why upper is sum?
    while (true) {
      int mid = (lower + upper) / 2;
      int blocks = calculateBlockCount(A, mid); // don't I have specified number of blocks? What blocks do? Don't get that.
      if (blocks < K) {
        upper = mid - 1;
      } else if (blocks > K) {
        lower = mid + 1;
      } else {
        return upper;
      }
    }
  }

  private static int calculateBlockCount(int[] array, int maxSum) {
    int count = 0;
    int sum = array[0];
    for (int i = 1; i < array.length; i++) {
      if (sum + array[i] > maxSum) {
        count++;
        sum = array[i];
      } else {
        sum += array[i];
      }
    }
    return count;
  }

  // returns sum of all elements in an array
  private static int sum(int[] input) {
    int sum = 0;
    for (int n : input) {
      sum += n;
    }
    return sum;
  }

  // returns max value in an array
  private static int max(int[] input) {
    int max = -1;
    for (int n : input) {
      if (n > max) {
        max = n;
      }
    }
    return max;
  }

推荐答案

所以代码的作用是使用一种形式的二进制搜索(在这里,

So what the code does is using a form of binary search (How binary search works is explained quite nicely here, https://www.topcoder.com/community/data-science/data-science-tutorials/binary-search/. It also uses an example quite similar to your problem.). Where you search for the minimum sum every block needs to contain. In the example case, you need the divide the array in 3 parts

进行二进制搜索时,您需要定义2个边界,可以确定在两个边界之间找到答案.此处,下边界是数组(lower)中的最大值.对于此示例,该值为5(这是将数组分成7个块的情况).

When doing a binary search you need to define 2 boundaries, where you are certain that your answer can be found in between. Here, the lower boundary is the maximum value in the array (lower). For the example, this is 5 (this is if you divide your array in 7 blocks). The upper boundary (upper) is 15, which is the sum of all the elements in the array (this is if you divide the array in 1 block.)

现在是搜索部分:在solution()中,您从边界和中点开始(示例为10). 在calculateBlockCount中,您计算​​(count ++这样),如果总和最大为10(在calculateBlockCount中为中间点/或maxSum),则可以进行多少个块.
对于示例10(在while循环中),这是2个块,现在代码将此(blocks)返回到solution.然后,它检查是小于还是大于K,这是所需的块数.如果它的值小于K,则您的mid点很高,因为要在块中放入许多数组元素.如果它大于K,则说明您的mid点太高,并且您在数组中放置的数组元素太少. 现在在检查之后,将求解空间减半(upper = mid-1). 这种情况在每个循环中都会发生,它使解决方案空间减半,从而使其收敛非常快.

Now comes the search part: In solution() you start with your bounds and mid point (10 for the example). In calculateBlockCount you count (count ++ does that) how many blocks you can make if your sum is a maximum of 10 (your middle point/ or maxSum in calculateBlockCount).
For the example 10 (in the while loop) this is 2 blocks, now the code returns this (blocks) to solution. Then it checks whether is less or more than K, which is the number of blocks you want. If its less than K your mid point is high because you're putting to many array elements in your blocks. If it's more than K, than your mid point is too high and you're putting too little array elements in your array. Now after the checking this, it halves the solution space (upper = mid-1). This happens every loop, it halves the solution space which makes it converge quite quickly.

现在,您在调整mid的同时继续进行操作,直到给出输入K中的数量块为止.

Now you keep going through your while adjusting the mid, till this gives the amount blocks which was in your input K.

所以要逐步进行:

Mid =10 , calculateBlockCount returns 2 blocks
solution. 2 blocks < K so upper -> mid-1 =9, mid -> 7  (lower is 5)
Mid =7 , calculateBlockCount returns 2 blocks  
solution() 2 blocks < K so upper -> mid-1 =6, mid -> 5 (lower is 5, cast to int makes it 5)
Mid =5 , calculateBlockCount returns 4 blocks
solution() 4 blocks < K so lower -> mid+1 =6, mid -> 6  (lower is 6, upper is 6
Mid =6 , calculateBlockCount returns 3 blocks
So the function returns mid =6....

希望这会有所帮助,

GL学习编码:)

这篇关于搜寻最小大数的算法需要说明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆