编程珠玑 第八章 习题

 

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;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值