8、修改分治算法,使得递归的最坏性能为线性时间
编程珠玑里面提示说,需要记录Last Set Index,于是我便记录之,但是问题是,如此最坏是不能线性的,最好是O(n),就是左右都是第一个节点的时候。
int subquadratic_conquer(int arry[], int l, int r)
{
int lmax;
int rmax;
int sum;
int sub_l = l;
int sub_r = r;
if (l > r)
{
return 0;
}
if (l == r)
{
return max(0, arry[l]);
}
int m = (l + r) / 2;
lmax = sum = 0;
for (int i = m; i >= l; i--) //跨边界最大子向量在a中部分是a中包含右边界的最大子向量
{
sum += arry[i];
if(sum > lmax)
{
sub_l = i;
}
lmax = max(lmax, sum);
}
rmax = sum = 0;
for (int j = m + 1; j <= r; j++) //跨边界最大子向量在b中部分是b中包含左边界的最大子向量
{
sum += arry[j];
if(sum > rmax)
{
sub_r = j;
}
rmax = max(rmax, sum);
}
return max(lmax + rmax, max(subquadratic_conquer(arry, sub_l, m), subquadratic_conquer(arry, m + 1, sub_r)));//返回3个总和中的最大者
}
int main()
{
int a[6] = {3, 4, -2, -9, 10, 8};
int sub_max = subquadratic_conquer(a, 0, 5);
return 0;
}
9、全负数数组,用求最大子向量求和的方式求最大元素的值:
这个问题很简单了,因为全负数,任意数相加必然更小,要最大子序列,就不能加,然后找到最大值,但是不能用iter方式咯,就用求最大子序列的和的方式,如下。
int maximum(int arry[], int n)
{
int maxsofar = arr[n-1];
int maxendinghere = 0;
for (int i = 0; i < n; i++)
{
maxendinghere = max(maxendinghere + arr[i], 0);
maxsofar = max(maxsofar, maxendinghere);
}
return maxsofar;
}
10、求最接近0的子向量
这个也不难,做另一个数组存储cum,使得cum[i] = cum[i-1] + arr[i],arr[]为原始数组。如果cum[l-1] = cum[n],那么cum[l..n]就是最接近0子向量,这里一定是0.但是,最接近0的子向量也很差不多,只要把所有的cum排序就是了,delta最小的就是了,整个算法复杂度就是排序了。
int approximate(int * pArry, int len)
{
int * cum = 0;
int * realarry = new int[len + 1];
realarry[0] = 0;
cum = realarry + 1; //cum[-1] = 0
//累计pArry[0....i]的和存放于cum[i]中
for (int i = 0; i < len; i++)
{
cum[i] = cum[i - 1] + pArry[i];
}
sort(cum, cum + len); //对cum排序
int iMin = cum[1] - cum[0];
for (int k = 1; k < len; k++)
{
iMin = min(iMin, cum[k] - cum[k - 1]); //返回相邻两个元素差值最小的
}
return iMin;
}