牛客练习记录第六周

第一题:https://www.nowcoder.com/practice/c3b49a12eb344ca3939f6a6232347397?tpId=98&tqId=32914&rp=5&ru=/ta/2019test&qru=/ta/2019test/question-ranking

题目描述

一组带数字编号的球里除了两个编号之外,其它的编号都出现了两次。
请写程序找出这两个只出现一次的编号。要求时间复杂度是O(n),空间复杂度是O(1)。

输入描述:

整形数组
长度不超过1000000

输出描述:

输出数组中2个只出现了一次的数
先输出较小的数

解题思路:

这个题目的突破口在哪里?题目为什么要强调有一个数字出现一次,其他的出现两次?我们想到了异或运算的性质:任何一个数字异或它自己都等于0 。也就是说,如果我们从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现一次的数字,因为那些出现两次的数字全部在异或中抵消掉了。

有了上面简单问题的解决方案之后,我们回到原始的问题。如果能够把原数组分为两个子数组。在每个子数组中,包含一个只出现一次的数字,而其它数字都出现两次。如果能够这样拆分原数组,按照前面的办法就是分别求出这两个只出现一次的数字了。

我们还是从头到尾依次异或数组中的每一个数字,那么最终得到的结果就是两个只出现一次的数字的异或结果。因为其它数字都出现了两次,在异或中全部抵消掉了。由于这两个数字肯定不一样,那么这个异或结果肯定不为0 ,也就是说在这个结果数字的二进制表示中至少就有一位为1 。我们在结果数字中找到第一个为1 的位的位置,记为第N 位。现在我们以第N 位是不是1 为标准把原数组中的数字分成两个子数组,第一个子数组中每个数字的第N 位都为1 ,而第二个子数组的每个数字的第N 位都为0 。

#include<iostream>
#include<algorithm>
#include<string>
#include<math.h>
#include<stdlib.h>
#include <iostream>
#include<cstring>
#include<cstdio>
using namespace std;

struct ListNode
{
    int m_nKey;
    ListNode* m_pNext;
};

int main(){
	int n,sum=0;
	int a[1000001];
	while(cin>>a[n]){
		sum^=a[n];
		n++;
	}
	int t=0;
	while((sum&1)==0){
		t++;
		sum=sum>>1;
	} 
	int num=0,num2=0;
	for(int i=0;i<n;i++){
		if((a[i]>>t)&1) num^=a[i];
		else num2^=a[i];
	}
	cout<<min(num,num2)<<' ';
	cout<<max(num,num2);
	return 0;
} 
/*

*/

第二题:https://www.nowcoder.com/practice/7d78d8f671c2461aaeb304efb74b2310?tpId=98&tqId=32924&rp=5&ru=/ta/2019test&qru=/ta/2019test/question-ranking

题目描述

小米之家是成人糖果店。里面有很多便宜,好用,好玩的产品。中秋节快到了,小米之家想给米粉们准备一些固定金额大礼包。对于给定的一个金额,需要判断能不能用不同种产品(一种产品在礼包最多出现一次)组合出来这个金额。聪明的你来帮帮米家的小伙伴吧。

输入描述:

输入 N (N 是正整数, N  <= 200)
输入 N 个价格p(正整数, p <= 10000)用单空格分割
输入金额 M(M是正整数,M <= 100000 )

输出描述:

能组合出来输出 1
否则输出 0

示例1

输入

复制

6
99 199 1999 10000 39 1499
10238

解题思路:

#include<iostream>
#include<algorithm>
#include<string>
#include<math.h>
#include<stdlib.h>
#include <iostream>
#include<cstring>
#include<cstdio>
using namespace std;

int main(){
	int dp[100001]={0};
	int a[100001];
	int n;
	cin>>n;
	dp[0]=1;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	int m;
	cin>>m;
	for(int i=0;i<n;i++){
		for(int j=m;j>=a[i];j--){
			if(dp[j-a[i]]==1){
				dp[j]=1;
			}
//			cout<<dp[j]<<' '; 
		}
//		cout<<endl;
	}
	cout<<dp[m];
	return 0;
} 
/*

6 
3 3 4 4 7 8
9

*/

0-1揹包,又和0-1揹包不太一样;只有放进去才有分;

https://www.nowcoder.com/practice/6da9a72adb3741ac8f2787358ecda265?tpId=98&tqId=32926&rp=5&ru=/ta/2019test&qru=/ta/2019test/question-ranking

题目描述

小米食堂每年都会举办一次厨艺大赛,假设参赛的厨师一共有n位(n < 1000),比赛结束后没有公布评分,但是站在领奖台上的一排厨师中每位厨师都能看到与自己相邻的厨师(左或者

#include<iostream>
#include<algorithm>
#include<string>
#include<math.h>
#include<stdlib.h>
#include <iostream>
#include<cstring>
#include<cstdio>
using namespace std;

int main(){
	int a[100001];
	int b[100001];
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
		b[i]=1;
	}
	for(int i=1;i<n;i++){
		if(a[i]>a[i-1]) b[i]=b[i-1]+1;
	}
	int sum=b[n-1];
	for(int i=n-2;i>=0;i--){
		if(a[i]>a[i+1]) b[i]=max(b[i],b[i+1]+1);
		sum+=b[i];
//		cout<<b[i]<<' ';
	}
	cout<<sum;
	return 0;
} 
/*

6 
3 3 4 4 7 8
9

*/

右)里评分比自己低(看不到比自己分数高的人的分数)的评分。比赛结束之后要发奖金,以1K为单位,每位厨师至少会发1K的奖金,另外,如果一个厨师发现自己的奖金没有高于比自己评分低的厨师的奖金,就会不满意,作为比赛组织方,小米食堂至少需要发放多少奖金才能让所有厨师满意。

输入描述:

每组数据为n+1个正整数单空格分割,其中第一个数为参赛厨师的人数,后面n个数为每位厨师的得分(0-100)

输出描述:

输出至少需要多少K的奖金

示例1

输入

复制

10 60 76 66 76 85 55 61 71 84 62

从左至右,看自己左侧的厨师分数,比自己小的,在他的基础上加一

从右至左,看自己右侧的厨师分数,比自己小的,max(自己,右侧+1)

#include<iostream>
#include<algorithm>
#include<string>
#include<math.h>
#include<stdlib.h>
#include <iostream>
#include<cstring>
#include<cstdio>
using namespace std;

int main(){
	int a[100001];
	int b[100001];
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
		b[i]=1;
	}
	for(int i=1;i<n;i++){
		if(a[i]>a[i-1]) b[i]=b[i-1]+1;
	}
	int sum=b[n-1];
	for(int i=n-2;i>=0;i--){
		if(a[i]>a[i+1]) b[i]=max(b[i],b[i+1]+1);
		sum+=b[i];
//		cout<<b[i]<<' ';
	}
	cout<<sum;
	return 0;
} 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章