多多笔试7.25笔试复盘

题目1:
  输入一个N代表组数,接下来输入N组,每组2个数字空格隔开,代表线段的两端,如果存在任意一对线段存在包含关系就返回true,否则返回false.
思路:
  考虑两两组合判断,时间复杂度是o(N^2),一种排序,一种不排序,但是遍历时要考虑先后包含关系。
  优化算法:其实我们只需要考虑右边界

#include<bits/stdc++.h>
using namespace std;
int main(){
    int N; cin>>N;
    vector<vector<int>>nums(N,vector<int>(2));
    for(int i=0;i<N;i++){
        for(int j=0;j<2;j++)
            cin>>nums[i][j];
    }
    //完成输入
    //暴力法
    bool flag=false;
    sort(nums.begin(),nums.end()); 
    int pre=-1;
    for(int i=0;i<N-1;i++){
     if(nums[i][1]<=pre){
      flag=true; 
      break;
  }
  pre=max(pre,nums[i][1]);  //记录了截至目前的右边界最大值。 如果我右侧比这个最大值要小就妥了 
    }
    if(flag)
     cout<<"true";
    else
  cout<<"false";
}
#include<bits/stdc++.h>
using namespace std;
int main(){
    int N; cin>>N;
    vector<vector<int>>nums(N,vector<int>(2));
    for(int i=0;i<N;i++){
        for(int j=0;j<2;j++)
            cin>>nums[i][j];
    }
    //完成输入
    //暴力法
    bool flag=false;
    for(int i=0;i<N-1;i++){
    	for(int j=i+1;j<N;j++){
    		if(nums[i][0]<=nums[j][0] && nums[i][1]>=nums[j][1]){
            	flag=true;
           		break;
        	}        
        	if(nums[j][0]<=nums[i][0] && nums[j][1]>=nums[i][1]){
            	flag=true;
            	break;
        	}           	
		}  
		if(flag)
			break;    
    }
    cout<<flag;
}
#include<bits/stdc++.h>
using namespace std;
int main(){
    int N; cin>>N;
    vector<vector<int>>nums(N,vector<int>(2));
    for(int i=0;i<N;i++){
        for(int j=0;j<2;j++)
            cin>>nums[i][j];
    }
    //完成输入
    //排序的话
	sort(nums.begin(),nums.end()) ; //从小大到,因为是nums的元素,那就是行为基础进行排序,只会看第一个 
    bool flag=false;
    for(int i=0;i<N-1;i++){
    	for(int j=i+1;j<N;j++){
    		if(nums[i][0]<=nums[j][0] && nums[i][1]>=nums[j][1]){
            	flag=true;
           		break;
        	}                 	
		}  
		if(flag)
			break;    
    }
    cout<<flag;
}

题目2:
 多多鸡和多多鸭来打牌,每个人手上N个牌,按顺序出,多多鸡先出,依次放到桌面从左到右,如果遇到相同的牌,两个相同牌之间的牌连同该牌被出牌者收走,然后必须再出1张牌。如果打完了就其他人出,如果台面上剩余牌,奇数数值牌给多多鸡,偶数数值牌给多多鸭。输入第一行是N,第二行是多多鸡的手牌,第三行是多多鸭的手牌。
思路:
  看来以后要多关注下模拟的题目,这个题目先不用想太花里胡哨的,模拟即可,因为数据范围就是牌的数值是1-13,如果数字比较小,就模拟把,出牌数量忘记了,反正也不是非常多,这个线性打出来所以速度比较快的
  下面附上一种巧妙的解法和我的笨方法:

#include <bits/stdc++.h>
using namespace std;
int f(int p, vector<int> &cards)
{
    int i = 0, ret = 0;
    while (i != cards.size() && cards[i] != p)
        ++i;
    if (i != cards.size())
    {
        ret = cards.size() - i + 1;
        cards.resize(i);
    }
    else
        cards.push_back(p);
    return ret;
}
int main()
{
    int N, A = 0, B = 0, i = 0, j = 0;
    cin >> N;
    vector<int> a(N), b(N), cards;
    for (int i = 0; i < N; ++i)
        cin >> a[i];
    for (int i = 0; i < N; ++i)
        cin >> b[i];
    while (i < N || j < N)
    {
        while (i < N)
        {
            int t = f(a[i++], cards);
            A += t;
            if (t == 0)
                break;
        }
        while (j < N)
        {
            int t = f(b[j++], cards);
            B += t;
            if (t == 0)
                break;
        }
    }
    for (auto i : cards)
        i % 2 ? A++ : B++;
    cout << A << " " << B << "\n";
}

#include<bits/stdc++.h>
using namespace std;
int main(){
    int N; cin>>N;
    vector<int>res1(N); vector<int>res2(N);
    for(int i=0;i<N;i++)
    	cin>>res1[i];
    for(int j=0;j<N;j++)
    	cin>>res2[j];
   	//完成输入,进入模拟阶段
	stack<int>stk; vector<int>nums;
	unordered_map<int,int> map;//Value和index 
	int i=0,j=0,count1=0,count2=0;
	
	while( i<N || j<N ){
		if(!map.count(res1[i]) && i<N)	{
			map[res1[i]]=nums.size(); nums.push_back(res1[i]); stk.push(res1[i]);i++;  
		} //如果是哈希表里面没有出现过的
		
		else if(map.count(res1[i]) && i<N){
			count1++;
			int del=map[res1[i]]; nums.erase(nums.begin()+del,nums.end());
			unordered_map<int,int>::iterator it;
			while(stk.top()!=res1[i]){ //也就是这里进栈了 出问题了
			    cout<<stk.top()<<" ";	 
				int temp=stk.top(); stk.pop(); count1++;
		        //删除哈希表元素 
				for(it=map.begin();it!=map.end();it++){
					if(it->first==temp){
						map.erase(it);
						break;
					}
						
				}
			}
			for(it=map.begin();it!=map.end();it++){
				if(it->first==res1[i]){
					map.erase(it);
					break;
				} 
					
			}
			stk.pop(); count1++; i++;	
			continue;		
		}//如果哈希表里面出现过了
		 
		
		
		//
		if(!map.count(res2[j]) && j<N)	{
			map[res2[j]]=nums.size(); nums.push_back(res2[j]);stk.push(res2[j]);j++; 
		} //如果是哈希表里面没有出现过的
		
		在这里改下吧, 
		else if(map.count(res2[j]) && j<N){
			count2++;
			int del=map[res2[j]]; nums.erase(nums.begin()+del,nums.end());
			unordered_map<int,int>::iterator it;
			while(stk.top()!=res2[j]){
				int temp=stk.top(); stk.pop(); count2++;
				for(it=map.begin();it!=map.end();it++){
					if(it->first==temp){
						map.erase(it);
						break;
					}
				}
			}
			for(it=map.begin();it!=map.end();it++){
				if(it->first==res2[j]){
					map.erase(it);
					break;
				}				
			}
			stk.pop(); count2++; j++;
			///接着走,新的元素没出现就过了 
			if(!map.count(res2[j]) && j<N ) {
				map[res2[j]]=nums.size(); nums.push_back(res2[j]); stk.push(res2[j]);j++;
			}
			else if(map.count(res2[j]) && j<N){ //如果出现了 
				while(map.count(res2[j]) && j<N){
					count2++;
					int del=map[res2[j]]; nums.erase(nums.begin()+del,nums.end());
					unordered_map<int,int>::iterator it;
					while(stk.top()!=res2[j]){ //也就是这里进栈了 出问题了
						int temp=stk.top(); stk.pop(); count2++;
		        //删除哈希表元素 
						for(it=map.begin();it!=map.end();it++){
							if(it->first==temp){
								map.erase(it);
								break;
							}				
						}
					}
					for(it=map.begin();it!=map.end();it++){
						if(it->first==res2[j]){
							map.erase(it);
							break;
						} 			
					}
					stk.pop(); count2++; j++;
				}	
			}
								
	}
}
	
	//输出结果 
 	for(int i=0;i<nums.size();i++){
 		if(nums[i]%2)
			count1++;
		if(nums[i]%2==0)
			count2++;	
	}
	int size=nums.size();
    cout<<count1<<" "<<count2<<" "<<size; 

	
}

题目3:
  第三题是比如集合原来有个A元素,然后我们设置输入一个B和C元素,A+B和A*C都是集合的元素,然后根据BC来不断扩充集合,现在我们有一个target值,如果target值在集合中,我们输出1,不在集合我们输出0.给N组这样的数,来输出0 1这样的列向量。
思路:
  一开始我是用优先队列和哈希表来实现,但是只能过百分之15,可能要加上long吧,忘记加了,然后其实不用优先队列,我在队列里面加个条件都必须小于target才能进,这样反而会节省排序时间。下面的懒得改了。 哈希表是为了避免重复的扩张。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n; cin>>n;
    vector<vector<int>>nums(n,vector<int>(4));
    for(int i=0;i<n;i++){
        for(int j=0;j<4;j++)
            cin>>nums[i][j];
    }
    //完成输入 进行计算环节
    vector<int>res(n,0);
    //用队列的形式把
    for(int i=0;i<n;i++){
        priority_queue<int,vector<int>,greater<int> >q;
        unordered_set<int>set;
        int b=nums[i][1],c=nums[i][2],target=nums[i][3];
        q.push(nums[i][0]);set.insert(nums[i][0]);
        while(!q.empty() && q.top()<=target){
            int size=q.size();
            for(int i=0;i<size;i++){
                int temp=q.top();q.pop();
                int nb=temp+b,nc=temp*c;
                if(!set.count(nb)){
                    q.push(nb);
                    set.insert(nb);
                }
                    
                if(!set.count(nc)){
                    q.push(nc);    
                    set.insert(nc);
                }                 
            } //for循环结束
            if(set.count(target)){
                    res[i]=1;
                    break;
            }
        }/while   
		cout<<res[i]<<'\n';     
    }//循环结束
    
}

其实正确的思路是,注意到扩张的元素中包含了A+B,A+2B,A+NB和 AC,ACC。。。。可能会重复,但是不管怎么说,数字如果比原来的大就可能了。大致分为2类。如果存在,target-A 应该是B的倍数,如果满足就直接return1了,如果不满足,就A=AC;,然后这个新的A看看是不是B的倍数~这样。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n; cin>>n;
    vector<vector<int>>nums(n,vector<int>(4));
    for(int i=0;i<n;i++){
        for(int j=0;j<4;j++)
            cin>>nums[i][j];
    }
    //完成输入 进行计算环节
    vector<int>res(n,0);
    //用队列的形式把
    for(int i=0;i<n;i++){
    	int A=nums[i][0],b=nums[i][1],c=nums[i][2],target=nums[i][3];
    	while(A<=target){
    		if((target-A)%b==0){  //如果A是target就出现1了 
    			res[i]=1; break;	
			}
			A=A*c;		
		}
      
		cout<<res[i]<<'\n';     
    }//循环结束
    
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值