求连续子序列的最大和最小和。
1.暴力求解,采用三层循环
/**
* 暴力循环
* @param arr
*/
public static int method1(Integer[] arr){
int maxSum = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = i; j < arr.length; j++) {
int sum = 0;
for (int j2 = i; j2 <=j; j2++) {
sum += arr[j2];
}
if(sum>maxSum){
maxSum = sum;
}
}
}
return maxSum;
}
2.暴力优化
a、最里面一层循环简化。
/**
* 暴力循环优化
* @param arr
*/
public static int method2(Integer[] arr){
int maxSum = 0;
for (int i = 0; i < arr.length; i++) {
int sum = 0;
for (int j = i; j < arr.length; j++) {
sum += arr[j];
if(sum>maxSum){
maxSum = sum;
}
}
}
return maxSum;
}
b、合并相连正负元素,减少集合数量,降低运行时间。
/**
* 1、将连续的正数和负数合并,成为一个新数组,用list保存。
* @param arr
*/
public static int method4(Integer[] arr){
int count = 0;
List<Integer> list = new ArrayList<>();
//O(n)
for (int i = 0; i < arr.length; i++) {
if(count*arr[i]>=0){
count +=arr[i];
}
else{
list.add(count);
count =arr[i];
}
}
list.add(count);
//正负交替的一个链表结构。
// System.out.println(list);
//在调用递归。
Integer[] i = list.toArray(new Integer[list.size()]);
return method2(i);
}
3.分治法
/**
* 分治法,递归查找
* @param arr
*/
public static int method3(Integer[] arr,int l,int r){
if(l == r){
return arr[l]>0?arr[l]:0;
}
int lm = 0,rm = 0;
int tm = 0;
//变成子数组的查找子串最大值问题。
int m = (l+r)/2;
lm = method3(arr,l,m);
rm = method3(arr,m+1,r);
//还有可能在中间
int lbm = 0,rbm = 0;
int lb = 0;
for (int i = m; i >=l; i--) {
lb += arr[i];
if(lb>lbm){
lbm =lb;
}
}
int rb = 0;
for (int i = m+1; i<=r; i++) {
rb += arr[i];
if(rb>rbm){
rbm =rb;
}
}
int bm = lbm+rbm;
tm = (lm>rm?(lm>bm?lm:bm):(rm>bm?rm:bm));
return tm;
}
4.线性算法。
/**
* 最短子串,大于0舍弃,
*/
public static int method6(Integer[] arr){
int sum=0;
int min = 0;
for (int i = 0; i < arr.length; i++) {
sum+= arr[i];
if(sum>0){
sum = 0;//重新开始计算子串
}
if(sum<min){
min = sum; //子串最大值开始更新。
}
}
return min;
}
计算最少连续子序列
1、将原序列取相反数,其他一致。
/**
* 最短子串,大于0舍弃,修改器正负值,按最大算取负数
*/
public int method7(Integer[] arr){
int sum=0;
int max = 0;
for (int i = 0; i < arr.length; i++) {
sum+= -arr[i];
if(sum<0){
sum = 0;//重新开始计算子串
}
if(sum>max){
max = sum; //子串最大值开始更新。
}
}
return -max;
}