数组中总和最接近t的子向量(编程珠玑《第八章》)

函数approximate和函数nearestZero是用来求最接近0的算法。函数nearestTot是用来求最接近t的算法,算法思想仍然是递归的分治算法,和求和最小子向量的算法很类似,复杂度为O(nlogn)。没有想出来更好的解决方案。

#include<iostream>
#include<algorithm>
usingnamespace std;
 
int nearestZero(intA[],int n)
{
         int*sum=newint[n];
         sum[0]=A[0];
         for(int i=1;i<n;i++)
                  sum[i]=sum[i-1]+A[i];
         sort(sum,sum+n);
         intresult=sum[0]-sum[1];
         for(int i=2;i<n;i++)
         {
                  result=min(result,sum[i]-sum[i-1]);
         }
         returnresult;
}
 
int nearestTot(intA[],int n,intt)
{
         if(n==1)
                  returnA[0];
         intmid=n>>1;
         intleft=mid-1,right=mid;
         intmidSum=A[left]+A[right],result=A[left--]+A[right++];
         while(left>=0|| right<n)
         {
                  intleftValue=left>=0?A[left]:INT_MAX>>1,rightValue=right<n?A[right]:INT_MAX>>1; //此处右移一位的原因是:如果不右移,则数据太大,导致下面的abs(result+leftValue-t)有可能出现负值,如result-t==1,则会出现这种情况,因此为了避免这种情况就都右移了一位。
                  if(abs(result+leftValue-t)<abs(result+rightValue-t))//如果加上左边值更接近t则加左边
                  {
                          result+=leftValue;
                          left--;
                  }
                  else//否则加右边
                  {
                          result+=rightValue;
                          right++;
                  }
                  if(abs(result-t)<abs(midSum-t))
                  {
                          midSum=result;
                  }
         }
 
         if(abs(midSum-t)<abs(nearestTot(A,mid,t)-t))
         {
                  if(abs(midSum-t)<abs(nearestTot(A+mid,n-mid,t)-t))
                          return midSum;
                  else
                  {
                          return nearestTot(A+mid,n-mid,t);
                  }
         }
         else
         {
                  if(abs(nearestTot(A,mid,t)-t)<abs(nearestTot(A+mid,n-mid,t)-t))
                          return nearestTot(A,mid,t);
                  else
                  {
                          return nearestTot(A+mid,n-mid,t);
                  }
         }
}
 
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]); //返回相邻两个元素差值最小的 
    } 
         delete[]realarry;
    returniMin; 
} 
 
int main()
{
         intA[]={-1,2,3,-5,50,10,-8};
         cout<<nearestTot(A,7,40);
 
         system("pause");
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值