題目描述
一組帶數字編號的球裏除了兩個編號之外,其它的編號都出現了兩次。
請寫程序找出這兩個只出現一次的編號。要求時間複雜度是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;
}
/*
*/
題目描述
小米之家是成人糖果店。裏面有很多便宜,好用,好玩的產品。中秋節快到了,小米之家想給米粉們準備一些固定金額大禮包。對於給定的一個金額,需要判斷能不能用不同種產品(一種產品在禮包最多出現一次)組合出來這個金額。聰明的你來幫幫米家的小夥伴吧。
輸入描述:
輸入 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揹包不太一樣;只有放進去纔有分;
題目描述
小米食堂每年都會舉辦一次廚藝大賽,假設參賽的廚師一共有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;
}