Chinaunix首页 | 论坛 | 博客
  • 博客访问: 18137
  • 博文数量: 5
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 58
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-29 18:43
文章分类
文章存档

2014年(5)

我的朋友

分类: C/C++

2014-04-25 21:01:28


点击(此处)折叠或打开

  1. 总感觉求最小子序列乘积有些问题,请高手证明下正确

  2. /*
  3.  *最小子序列和
  4.  *最大子序列乘积
  5.  *最小子序列乘积
  6.  */

  7. #include<stdio.h>

  8. #define MAX2(A,B)    ( (A>B)?A:B )
  9. #define MIN2(A,B) ( (A>B)?B:A )

  10. int min_sub_sum(int A[],int N);
  11. int max_sub_multi(int A[],int left,int right);

  12. int min_sub_multi(int A[],int left,int right);


  13. int main(void)
  14. {
  15.     int A[] = {4,0,0,3};
  16.     
  17.     for(int i = 0; i < sizeof(A)/sizeof(int);++i)
  18.         printf("%d ",A[i]);
  19.     putchar('\n');
  20.     
  21.     printf("最小子序列和为:%d\n", min_sub_sum(A,sizeof(A)/sizeof(int)) );
  22.     printf("最大子序列乘积为:%d\n", max_sub_multi(A,0,sizeof(A)/sizeof(int)-1) );
  23.     printf("最小子序列乘积为:%d\n", min_sub_multi(A,0,sizeof(A)/sizeof(int)-1) );
  24.     
  25.     return 0;
  26. }

  27. //o(N):最小子序列的和,如果最小子序列和为正数,那么返回最小的正数
  28. int min_sub_sum(int A[],int N)
  29. {
  30.     int i,min_sum,cur_sum;
  31.     int j;
  32.     min_sum = cur_sum = 0;
  33.     j = 0;
  34.     
  35.     for(i = 0;i < N; ++i)
  36.     {
  37.         if(A[i] >= 0)
  38.             j++;
  39.         cur_sum += A[i];
  40.         if(cur_sum < min_sum)
  41.             min_sum = cur_sum;
  42.         else if(cur_sum > min_sum)
  43.             cur_sum = 0;
  44.     }
  45.     
  46.     if(j == N)
  47.     {
  48.         min_sum = A[0];
  49.         for(i = 1; i < N; ++i)
  50.         {
  51.             if(A[i] < min_sum)
  52.                 min_sum = A[i];
  53.         }
  54.     }
  55.     
  56.     return min_sum;
  57. }

  58. //o(N*logN) 最大子序列乘积
  59. int max_sub_multi(int A[],int left,int right)
  60. {
  61.     int left_max,right_max,max_from_pos,max_from_neg;
  62.     int left_max_pos,right_max_pos,left_min_neg,right_min_neg;
  63.     int multi;
  64.     int i,center;
  65.     
  66.     if(left == right)
  67.         return A[left];
  68.     
  69.     center = (left+right) / 2;
  70.     
  71.     left_max = max_sub_multi(A,left,center);
  72.     right_max = max_sub_multi(A,center+1,right);
  73.     
  74.     //分界处扩至最左边序列乘积最大正值或者最小负值
  75.     left_max_pos = left_min_neg = 0;
  76.     multi = 1;
  77.     for(i = center;i >= left; --i)
  78.     {
  79.         multi *= A[i];
  80.         if(multi > 0 && multi > left_max_pos)
  81.             left_max_pos = multi;
  82.         if(multi < 0 && multi < left_min_neg)
  83.             left_min_neg = multi;
  84.     }
  85.     
  86.     //分界处扩至最右边序列最大正值或者最小负值
  87.     right_max_pos = right_min_neg = 0;
  88.     multi = 1;
  89.     for(i = center+1 ; i <= right ; ++i)
  90.     {
  91.         multi *= A[i];
  92.         if(multi > 0 && multi > right_max_pos)
  93.             right_max_pos = multi;
  94.         if(multi < 0 && multi < right_min_neg)
  95.             right_min_neg = multi;
  96.     }
  97.     
  98.     max_from_pos = left_max_pos*right_max_pos;
  99.     max_from_neg = left_min_neg*right_min_neg;
  100.     
  101.     //找出最大值
  102.     return MAX2( MAX2(left_max,right_max) , MAX2(max_from_pos,max_from_neg) );
  103. }


  104. //o(N*logN) 最小子序列乘积
  105. int min_sub_multi(int A[],int left,int right)
  106. {
  107.     int left_min,right_min,min_from_pos,min_from_neg;
  108.     int left_max_pos,right_max_pos,left_min_neg,right_min_neg;
  109.     int multi;
  110.     int i,center;
  111.     
  112.     if(left == right)
  113.         return A[left];
  114.     
  115.     center = (left+right) / 2;
  116.     
  117.     left_min = min_sub_multi(A,left,center);
  118.     right_min = min_sub_multi(A,center+1,right);
  119.     
  120.     //分界处扩至最左边序列乘积最大正值或者最小负值
  121.     left_max_pos = left_min_neg = 0;
  122.     multi = 1;
  123.     for(i = center;i >= left; --i)
  124.     {
  125.         multi *= A[i];
  126.         if(multi > 0 && multi > left_max_pos)
  127.             left_max_pos = multi;
  128.         if(multi < 0 && multi < left_min_neg)
  129.             left_min_neg = multi;
  130.     }
  131.     
  132.     //分界处扩至最右边序列最大正值或者最小负值
  133.     right_max_pos = right_min_neg = 0;
  134.     multi = 1;
  135.     for(i = center+1 ; i <= right ; ++i)
  136.     {
  137.         multi *= A[i];
  138.         if(multi > 0 && multi > right_max_pos)
  139.             right_max_pos = multi;
  140.         if(multi < 0 && multi < right_min_neg)
  141.             right_min_neg = multi;
  142.     }
  143.     
  144.     //处理最小子序列乘积大于0时情况
  145.     if(left_min_neg == 0 && right_min_neg == 0)
  146.         return MIN2( MIN2(left_min,right_min) , MIN2(left_max_pos,right_max_pos) );
  147.     
  148.     min_from_pos = left_max_pos*right_min_neg;
  149.     min_from_neg = left_min_neg*right_max_pos;    
  150.     return MIN2( MIN2(left_min,right_min) , MIN2(min_from_pos,min_from_neg) );
  151. }


阅读(1322) | 评论(2) | 转发(0) |
0

上一篇:cp命令简单实现

下一篇:没有了

给主人留下些什么吧!~~

Matrix_2014-05-16 22:14:27

这是cur_sum的变化情况
cur_sum : -1
cur_sum : -4
cur_sum : 0
cur_sum : 0
cur_sum : 0
cur_sum : -6
cur_sum : 0
cur_sum : 0
cur_sum : 0
cur_sum : 0

Matrix_2014-05-16 22:13:48

你好~你的最小子序列求和的函数有问题
你不能简单的抛弃之前的数,你可以拿这个数组进行验证
int ar[] = {-1, -3, 2, -3, 4, -6, 7, 8, 9, 10};
很明显最小子序列应该是-7 = -1 + -3 + 2 + -3 + 4 + -6
而你的程序给出的答案却是-6