输入一组整数,求出这组数字子序列和中最大值。也就是只要求出最大子序列的和,不必求出最大的那个序列。例如:
实现可参考:http://www.cnblogs.com/CCBB/archive/2009/04/25/1443455.html
<?php/** * 找出最大子序列和 */// 方法一、 最暴力的方法 O(N^3)function findMax1($data){ $max_value = 0; $max_start = 0; $max_end = 0; $data_num = count($data); for($i=0;$i<$data_num;$i++){ for($j=$i;$j<$data_num;$j++){ $sum = 0; $temp = array(); for($k=$i;$k<=$j;$k++){ $temp[] = $data[$k]; $sum += $data[$k]; } if($max_value < $sum){ $max_value = $sum; $max_start = $i; $max_end = $j; } } } return array($max_value,$max_start,$max_end);}//方法二、 记录上一次的结果 O(N^2)function findMax2($data){ $max_value = 0; $max_start = 0; $max_end = 0; $data_num = count($data); for($i=0;$i<$data_num;$i++){ $last_sum = 0; for($j=$i;$j<$data_num;$j++){ $sum = $last_sum+$data[$j]; if($max_value < $sum){ $max_value = $sum; $max_start = $i; $max_end = $j; } $last_sum = $sum; } } return array($max_value,$max_start,$max_end);}//方法三、分而自治算法 O(NlogN)function findMax3($data,$start=0,$end=0){ if($start >= $end){ $max_value = isset($data[$start])?$data[$start]:0; }else{ $mid = floor(($start+$end)/2); list($max_left_value,$max_left_start,$max_left_end) = findMax3($data,$start,$mid); list($max_right_value,$max_right_start,$max_right_end) = findMax3($data,$mid+1,$end); //计算左边的最大值 $max_this_value = $data[$mid]; $max_this_start = $mid; $max_this_end = $mid; $temp = 0; for($i=$max_this_start;$i>=$start;$i--){ $temp += $data[$i]; if($temp > $max_this_value){ $max_this_value = $temp; $max_this_start = $i; } } //计算右边的最大值 $temp = $max_this_value; for($i=$max_this_end+1;$i<=$end;$i++){ $temp += $data[$i]; if($temp > $max_this_value){ $max_this_value = $temp; $max_this_end = $i; } } $max_value = $max_this_value; $start = $max_this_start; $end = $max_this_end; if($max_value < $max_left_value){ $max_value = $max_left_value; $start = $max_left_start; $end = $max_left_end; } if($max_value < $max_right_value){ $max_value = $max_right_value; $start = $max_right_start; $end = $max_right_end; } } return array($max_value,$start,$end);}//方法四、找规律算法 O(N)function findMax4($data){ $max_value = 0; $thisSum = 0; $data_len = count($data); $start = 0; $end = 0; for($i=0;$i<$data_len;$i++){ $thisSum += $data[$i]; if($thisSum > $max_value){ $max_value = $thisSum; $end =$i; }else if($thisSum < 0){ $thisSum = 0; $start= $i+1; } } return array($max_value,$start,$end);}
<?php// 获取一个随机数列function getArrayData($len=0){ $arr_data = array('4','-6','8','2','-4','7','2','-5','1'); if($len != 0){ $arr_data = array(); for($i=0;$i<$len;$i++){ $arr_data[] = rand(-9,9); } } return $arr_data;}$arr_data = getArrayData(1000);echo implode(',',$arr_data);echo "\n";echo "*************findMax1:最暴力的方法**********\n";$start_time = time();list($max_value1,$start1,$end1)=findMax1($arr_data);echo "max_value:{$max_value1}\n";echo "index:{$start1}-{$end1}\n";echo 'take time:'.(time()-$start_time);echo "\n";echo "*************findMax2:记录上一次的结果**********\n";$start_time = time();list($max_value2,$start2,$end2)=findMax2($arr_data);echo "max_value:{$max_value2}\n";echo "index:{$start2}-{$end2}\n";echo 'take time:'.(time()-$start_time);echo "\n";echo "*************findMax3:分而治之算法**********\n";$start_time = time();list($max_value3,$start3,$end3)=findMax3($arr_data,0,count($arr_data)-1);echo "max_value:{$max_value3}\n";echo "index:{$start3}-{$end3}";echo "\n";echo 'take time:'.(time()-$start_time);echo "\n";echo "*************findMax4:找规律算法**********\n";$start_time = time();list($max_value4,$start4,$end4)=findMax4($arr_data);echo "max_value:{$max_value4}\n";echo "{$start4}-{$end4}";echo "\n";echo 'take time:'.(time()-$start_time);echo "\n";
测试结果:n=1000
还在测试中,第一种方案太慢了