算法与数据结构实验题 1.3 寻找幸运值

算法与数据结构实验题 1.3 寻找幸运值
★ 实验任务
给出两个已按升序排列的数组 a[1..n],b[1..m],如果存在 i,j,使得a[i]+b[j]==k,我们便说已找到幸运值。请你判断能不能找到幸运值。
★数据输入
输入第一行为正整数 n,m,k。(1<=k<=10^9)
第二行为 n 个正整数 a[1..n]。(1<=ai<=10^9)
第三行为 m 个正整数 b[1..m]。(1<=bi<=10^9)
80%的数据 1<=n,m<=1000.
100%的数据 1<=n,m<=100000.
★数据输出
如果能找到幸运值,输出 yes。否则输出 no。
输入示例
3 3 8
1 2 3
4 6 7
输出示例
yes

输入示例
3 3 4
1 2 3
4 6 7
输出示例
no


思路:
若是暴力枚举,则时间复杂度为O(n^2),对于20%的数据会超时。
改进:
k已知,对于a数组中的任意一个数,是否在b数组中存在k-a[i]?可以使用二分查找,时间复杂度降为O(nlnm)。
如果再优化,可以考虑n和m的大小,采取O(nlgm)或者O(mlgn)的算法。
附上代码

#include<iostream>    
using namespace std;      
int a[100001],b[100001];      

int found(int x,int y,int k)        //二分查找     
{      
    int mid=x+(y-x)/2;      
    if(x>y)                      //查找完毕没有找到答案,返回0      
        return 0;      
    else      
    {      
        if(b[mid]==k)      
            return 1;            //找到!返回1      
        else if(b[mid]>k)      
            return found(x,mid-1,k);     //找左边      
         else      
            return found(mid+1,y,k);     //找右边      
    }      
}      

int main()      
{      
    int n,m,k,i,j;      
    int flag=0;      
    cin>>n>>m>>k;      
    for(i=0;i<n;i++)      
    {      
        cin>>a[i];      
    }      
    for(i=0;i<m;i++)      
    {      
       cin>>b[i];    
    }      
    for(i=0;i<n;i++)                                    
    {      
        if(k-a[i]<=b[m-1])     //当b数组中有可能存在答案时,调用二分查找 
        {    
            if(found(0,m-1,k-a[i]))        
            {      
                flag=1;      
                break;  
            }  
        }      
    }      
    if(flag)  cout<<"yes"<<endl;      
    else  cout<<"no"<<endl;      
    return 0;      
}

经ACM大佬指点,对代码进行了进一步改进。
巧妙利用这两个数组递增的特性,仅需存入a数组,用变量cura存a数组的下标,定义cura初始值为n-1,将a数组倒序与数组b中的数字进行求和,若a[cura]+b大于k,则cura自减,继续读入数组b,继续求和判断,如此循环。若a[cura]+b=k,则跳出循环,输出yes;若当cura=0时a[cura]+b仍不等于k,则跳出循环,输出no。
时间复杂度降为O(n),空间复杂度也一并降低。
附上代码

#include<cstdio>  
#include<iostream>    
using namespace std;    
int a[100001], b;     
int main()    
{    
    int n,m,k,i,j,cura;    
    int flag=0;    
    cin>>n>>m>>k; cura = n - 1;  
    for(i=0;i<n;i++) scanf("%d", &a[i]);    //相较于C++的cin输入流,C语言的输入函数scanf能节省大量时间
    for(i=0;i<m;i++) 
    {  
        scanf("%d", &b);  
        while (cura >= 0 && a[cura] + b > k) cura--;  
        if (cura < 0)  break; 
        else if (a[cura] + b == k) 
        {  
            cout<<"yes"<<endl; return 0;  
        }  
    }  
    cout<<"no"<<endl;    
    return 0;    
}

感受到了大佬的力量233

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值