[关闭]
@elibinary 2017-02-26T05:03:39.000000Z 字数 2279 阅读 741

连续子向量最大和

未分类


求一串数字的最大连续子向量和,问题是这样的给出一个具有n个整数的向量,求出任何连续子向量中的最大和。

首先想到最暴力的求解方法:穷举。去穷举出所有的子向量然后求和比较即可,思想简单实现简单。可以很容易的给出实现:

  1. int max = 0;
  2. int length = SCALE;
  3. int i,j,k;
  4. for (i = 0; i < length; ++i)
  5. {
  6. for (j = i; j < length; ++j)
  7. {
  8. int sum = 0;
  9. for (k = i; k <= j; ++k)
  10. {
  11. sum += x[k];
  12. }
  13. max = maxnum(max, sum);
  14. }
  15. }

穷举法虽然简单易实现,但是上面的实现我们一眼就可以看出其时间复杂度是立方级的,也就是O(n^3).

看着上面的实现,可以发现其中有着很多的重复计算,那么容易想到可以把中间结果存储起来以备后面再次用到时可以直接取用以此来进行计算优化。

  1. max = 0;
  2. for (i = 0; i < length; ++i)
  3. {
  4. int sum = 0;
  5. for (j = i; j < length; ++j)
  6. {
  7. sum += x[j];
  8. max = maxnum(max, sum);
  9. }
  10. }

上述实现只保存了内层计算的中间结果,其时间复杂度O(n^2).
我们可以进一步简化其实现:

  1. max = 0;
  2. int max_end_here = 0;
  3. for (i = 0; i < length; ++i)
  4. {
  5. max_end_here = maxnum(max_end_here + x[i], 0);
  6. max = maxnum(max, max_end_here);
  7. }

上述这种实现的思路就是,如果到当前节点为止结果为正,就继续往后累加(基数为正必然总和会增大),如果为负就舍弃前面的连续,从当前位置开始重新计算连续向量和(如果为负继续累加必然会减小总和)。这样就把时间复杂度控制在了O(n)。

下面给出完整代码以及三种实现的时间度量及比较:

  1. #include <stdio.h>
  2. #include <time.h>
  3. #include <stdlib.h>
  4. #define SCALE 3000
  5. int maxnum(int a, int b);
  6. int main(int argc, char const *argv[])
  7. {
  8. FILE *fp;
  9. fp = fopen("maximum.in", "r");
  10. // int x[] = {1,12,-11,10,-65,54,22,-9,21,5,48,5,-8,-2,56,54,-88,-5,2,-8,554,-56,35,-55,555,-65,-545,-23,48,-5,88,-56,16,-8};
  11. int *x = (int *)malloc(sizeof(int)*(SCALE+1));
  12. int xi = SCALE,a = 0,num_in = 0;
  13. while(xi--){
  14. fscanf(fp, "%d", &x[a++]);
  15. }
  16. clock_t start, end;
  17. // ***Algorithm-1 cube***
  18. start = clock();
  19. int max = 0;
  20. int length = SCALE;
  21. int i,j,k;
  22. for (i = 0; i < length; ++i)
  23. {
  24. for (j = i; j < length; ++j)
  25. {
  26. int sum = 0;
  27. for (k = i; k <= j; ++k)
  28. {
  29. sum += x[k];
  30. }
  31. max = maxnum(max, sum);
  32. }
  33. }
  34. // long num = 10000000L;
  35. // while(num--);
  36. end = clock();
  37. double times = (double)(end - start)/CLOCKS_PER_SEC;
  38. double dend = (double)end;
  39. printf("\n***Algorithm-1 cube***\n");
  40. printf("end: %f\n", dend);
  41. printf("Time consuming: %f\n", times);
  42. printf("%d\n", max);
  43. // ***Algorithm-2 square***
  44. start = clock();
  45. max = 0;
  46. for (i = 0; i < length; ++i)
  47. {
  48. int sum = 0;
  49. for (j = i; j < length; ++j)
  50. {
  51. sum += x[j];
  52. max = maxnum(max, sum);
  53. }
  54. }
  55. end = clock();
  56. times = (double)(end - start)/CLOCKS_PER_SEC;
  57. dend = (double)end;
  58. printf("\n***Algorithm-2 square***\n");
  59. printf("end: %f\n", dend);
  60. printf("Time consuming: %f\n", times);
  61. printf("%d\n", max);
  62. // ***Algorithm-3 linear***
  63. start = clock();
  64. max = 0;
  65. int max_end_here = 0;
  66. for (i = 0; i < length; ++i)
  67. {
  68. max_end_here = maxnum(max_end_here + x[i], 0);
  69. max = maxnum(max, max_end_here);
  70. }
  71. end = clock();
  72. times = (double)(end - start)/CLOCKS_PER_SEC;
  73. dend = (double)end;
  74. printf("\n***Algorithm-3 linear***\n");
  75. printf("end: %f\n", dend);
  76. printf("Time consuming: %f\n", times);
  77. printf("%d\n", max);
  78. free(x);
  79. x = NULL;
  80. return 0;
  81. }
  82. int maxnum(int a, int b)
  83. {
  84. return a > b ? a : b;
  85. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注