1)输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个正数组成子数组,每个子数组都有一个和。求所有子数组的最大值。时间复杂度o(n)。
例如:输入1,-2,3,10,-4,7,2,5 和最大的子数组为3,10,-4,7,2 因此输出为该子数组的和18
public class MaxSubsum { /** * @param args * 求子数组的最大和 * 输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个正数组成子数组,每个子数组都有一个和。求所有子数组的最大值。时间复杂度o(n)。 * 例如:输入1,-2,3,10,-4,7,2,5 和最大的子数组为3,10,-4,7,2 因此输出为该子数组的和18 */ /** * max[0]记录子数组的最大值; * max[1]记录子数组的起始下标 * max[2]记录子数组的终止下标 * */ public static int[] maxSubsum(int[] a){ int[] max={0,0,0}; int sum=0; for(int i=0;i<a.length;i++){ sum+=a[i]; //若到当前值的和小于0,说明加入这串数字后,将使整体结果减小 //故舍掉这部分值,并从当前值的下一值开始,重新计数 if(sum<0){ sum=0; max[1]=i+1; } else if(sum>max[0]){ max[0]=sum; max[2]=i; } } return max; } public static void main(String[] args) { // TODO Auto-generated method stub int[] arr={1,-2,3,10,-4,7,2,-5}; int[] max=MaxSubsum.maxSubsum(arr); for(int i=max[1];i<=max[2];i++) System.out.print(arr[i]+","); System.out.println(); System.out.println(max[0]); } }
2)一根绳子长n米。将其切成几段(至少切一下),每段长度都是整数。请给出一种切法,使得切成的各段绳子之间的乘积是最大的。(即自然数N分解为n个自然数的和,求这n个数的乘积最大值)
思路:动态规划
分析:最优问题,可以用动态规划求解
1、描述最优解结构
N = a1 + a2 + ... + an;
M = a1 * a2 * ... * an;
求M的最大值
考虑到N = a + b,而a与b又可以分解为另外几个和为a或b的数的积,因此对于确定的N = a + b,有一个最优解M(N) = M(a)*M(N-a)。而a又有1到N/2种取值,所以有一般最优解M(N) = max{M(a) + M(N - a)}(a < N/2)。而对于1、2、3、4、5等的M值列一个表,就可以得到N<=4时,M(N) = N。于是有下列递归定义。
2、递归定义最优解
代码:
public static int M(int N){ int max=0; int temp=0; if(N<=4) return N; else{ for(int i=1;i<=N/2;i++){ temp=M(i)*M(N-i); if(temp>max) max=temp; } return max;} }