算法起步(3)抽签问题—合二为一(上)

抽签问题(C++)—合二为一(上)
你的朋友提议玩一个游戏:把写有数字的n个纸片放入一个袋子里,
你可以从中抽取4张纸片,每次抽取后把纸片放回到袋子里,如果
抽取的4张纸片上的数字和为m,就算你赢,否则你输,抽了很多
次,结果你完败,那么我可以胜利吗?假设纸牌上的数字依次为k1,
k2,k3,k4,….ki,试写一个程序判断你是否有胜利的可能
限制条件:
n(1,50)
m(1,10^8)
ki(1,10^8)

const int MAX_N = 50;
int main(){
    //是否查找到符合条件的组合的标志
    bool f=false;

    int n,m;
    int k[MAX_N];

    //从标准输入输入
    scanf("%d %d",&n,&m);
    for(i = 0;i<n;i++){
    scanf("%d",&k[i]);
}
    for(int a = 0;a<n;a++){
    for(int b = 0;b<n;b++){
    for(int c = 0;c<n;c++){
    for(int d = 0;d<n;d++){
    if(m==k[a]+k[b]+k[c]+k[d])
    f=true;
}
}
}
}
    //从标准输出输出
    if(f)
    //printf("%d/n",yes);
    puts("Yes");
    else{
    //printf("%d/n",no);
    puts("no");
}
}

是否觉得超级简单,那么问题来了,当n = 1000时,我们的算法复杂度1000^3,我们需要降低其复杂度

如何去做,如何结合二分法降低其复杂度
二分法:将数据从小到大排列,取中间数,如果比中间数大,在后半部分查找,如果比中间数小,在前半部分查找

    int n,m;
    int k[MAX_N];
    bool f = false;

    bool binary_search(int x)
    //k[l],k[l+1],k[l+2]....k[r-1]
    {
    while(r-1>1){
    int l=0;
    int r=n;
    int i=(l+r)/2;
    if(x>k[i])
    l=i+1;
    else if(x==k[i])
    return true;
    else
    r=i;
    }
    return false;
    }
    void solve(){
    sort(k,k+n);
    for(a = 0;a<n;a++){
    for(b = 0;b<n;b++){
    for(c = 0;c<n;c++){
    if(binary_search(m-k[a]-k[b]-k[c])){
    f = true;
}
}
}
}
    if(f)
    puts("Yes");
    else
    puts("no");
}
第一次优化算法后,让我们来看看复杂度
排序nlogn
循环n^3logn
n^3logn比nlogn大,所以复杂度为n^3logn
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值