1.排序
- 简单选择排序
int arr[]={9,8,7,6,0,1,2,3,4,5};
void selectSort(){
int index=0;
for(int i=0;i<sizeof(arr)/sizeof(int);i++){
int minIndex=index;
int min=arr[index];
for(int j=index+1;j<sizeof(arr)/sizeof(int);j++)
if(arr[j]<min){
minIndex=j;
min=arr[j];
}
arr[minIndex]=arr[index];
arr[index++]=min;
}
}
- 简单插入排序
int arr[]={9,8,7,6,0,1,2,3,4,5};
void insertSort(){
for(int i=1;i<sizeof(arr)/sizeof(int);i++){
int cur=arr[i],j;
for(j=i-1;j>=0;j--)
if(arr[j]>cur) arr[j+1]=arr[j];
else break;
arr[j+1]=cur;
}
}
- 结构体排序,使用sort函数
PAT甲级1025
#include<iostream>
#include<string>
#include <algorithm>
#include<vector>
using namespace std;
typedef struct stu{
string id;
int score,location,localRank;
}stu;
vector<stu> v;
bool cmp(stu a, stu b){
return a.score!=b.score? a.score>b.score:a.id<b.id;
}
int main(){
int n,m,num=0;
cin>>n;
for(int i=0;i<n;i++){
cin>>m;
for(int j=0;j<m;j++){
stu temp;
cin>>temp.id>>temp.score;
temp.location=i+1;
v.push_back(temp);
num++;
}
sort(v.begin()+num-m,v.begin()+num,cmp);
v[num-m].localRank=1;
for(int j=num-m+1;j<num;j++)
if(v[j].score!=v[j-1].score) v[j].localRank=j-(num-m)+1;
else v[j].localRank=v[j-1].localRank;
}
cout<<v.size()<<endl;
sort(v.begin(),v.begin()+num,cmp);
int curRank=1;
for(int i=0;i<v.size();i++)
if(i==0||v[i].score!=v[i-1].score){
cout<<v[i].id<<" "<<i+1<<" "<<v[i].location<<" "<<v[i].localRank<<endl;
curRank=i+1;
}
else
cout<<v[i].id<<" "<<curRank<<" "<<v[i].location<<" "<<v[i].localRank<<endl;
return 0;
}
2.散列
- 自编小题:输入N个字符串与M个查询字符串,输出该字符串在N个字符串中出现的个数。
样例输入
4 3
abc
abc
a
e
f
e
abc
样例输出
4 3
abc
abc
a
e
f
e
abc
字符串:f,该字符串未出现
字符串:e,出现次数为1
字符串:abc,出现次数为2
#include<iostream>
#include<string>
#include<map>
#include<vector>
using namespace std;
int main(){
map<string,int> myMap;
vector<string> v;
int n,m;
string temp;
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>temp;
map<string,int>::iterator it=myMap.find(temp);
if(it!=myMap.end()) it->second++;
else myMap.insert(pair<string,int>(temp,1));
}
for(int i=0;i<m;i++){
cin>>temp;
map<string,int>::iterator it=myMap.find(temp);
if(it!=myMap.end()) v.push_back("字符串:"+temp+",出现次数为"+to_string(it->second));
else v.push_back("字符串:"+temp+",该字符串未出现");
}
for(string s:v) cout<<s<<endl;
return 0;
}
- 字符串哈希函数(字符串中只允许有大小写字母与数字)
int hashFunc(string s){
int result=0;
for(int i=0;i<s.size();i++){
if(s[i]>='a'&&s[i]<='z') result=result*62+(s[i]-'a');
else if(s[i]>='A'&&s[i]<='Z') result=result*62+(s[i]-'A')+26;
else result=result*62+(s[i]-'0')+52;
}
return result;
}
3.递归
- 自编小题:输入给定的数字个数N,下一行给出N个0-9的数字可以重复,输出这N个数字的全排列。
#include<iostream>
#include<vector>
using namespace std;
int N,flag[10],temp;
vector<int> v;
void f(int pos){
if(pos==N){
for(int i=0;i<v.size();i++)
if(i==v.size()-1) cout<<v[i]<<endl;
else cout<<v[i]<<" ";
}
else{
for(int i=0;i<10;i++)
if(flag[i]>0){
flag[i]--;
v[pos]=i;
f(pos+1);
flag[i]++;
}
}
}
int main(){
scanf("%d",&N);
v.resize(N);
for(int i=0;i<N;i++){
scanf("%d",&temp);
flag[temp]++;
}
f(0);
return 0;
}
输入
4
0 1 4 5
输出
0 1 4 5
0 1 5 4
0 4 1 5
0 4 5 1
0 5 1 4
0 5 4 1
1 0 4 5
1 0 5 4
1 4 0 5
1 4 5 0
1 5 0 4
1 5 4 0
4 0 1 5
4 0 5 1
4 1 0 5
4 1 5 0
4 5 0 1
4 5 1 0
5 0 1 4
5 0 4 1
5 1 0 4
5 1 4 0
5 4 0 1
5 4 1 0
- N皇后问题
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
int N,flag[10],total=0;
vector<int> v;
void f(int pos){
if(pos==N) total++;
else
for(int i=1;i<=N;i++){
bool flag1=true;
if(!flag[i]){
v[pos]=i;
for(int j=0;j<pos;j++)
if(fabs(j-pos)==fabs(v[j]-v[pos])){
flag1=false;
break;
}
if(flag1){
flag[i]=1;
f(pos+1);
flag[i]=0;
}
}
}
}
int main(){
scanf("%d",&N);
v.resize(N);
f(0);
cout<<total;
return 0;
}
输入
8
输出
92
4.贪心
#include<iostream>
#include<algorithm>
using namespace std;
struct mooncake{
float volume;
float value;
float price;
};
bool cmp(struct mooncake a,struct mooncake b){
return a.price>b.price;
}
int main(){
int typeNum;
float income=0,total;
cin>>typeNum>>total;
struct mooncake record[typeNum];
for(int i=0;i<typeNum;i++) cin>>record[i].volume;
for(int i=0;i<typeNum;i++){
cin>>record[i].value;
record[i].price=record[i].value/record[i].volume;
}
sort(record,record+typeNum,cmp);
for(struct mooncake m:record){
if(m.volume>=total){
income+=m.price*total;
break;
}
else{
income+=m.value;
total-=m.volume;
}
}
printf("%.2f",income);
return 0;
}
#include<iostream>
using namespace std;
int main(){
int record[10],temp;
int min=9;
double result=0;
for(int i=0;i<10;i++){
cin>>temp;
record[i]=temp;
if(i!=0&&record[i]>0&&i<min) min=i;
}
cout<<min;
record[min]--;
for(int i=0;i<10;i++)
for(int j=0;j<record[i];j++)
cout<<i;
return 0;
}
- 输入区间个数N,接着输入N个开区间,区间左边界在前右边界在后。在保证区间相互不相交的条件下输出最大可放置区间数
样例输入
4
1 3
2 4
3 5
6 7
样例输出
3
#include<iostream>
#include<algorithm>
using namespace std;
typedef struct section{
int left,right;
}section;
bool cmp(section a,section b){
if(a.left!=b.left) return a.left>b.left;
else return a.right<b.right;
}
int main(){
int n,result=0,preLeft=-1;
cin>>n;
section record[n];
for(int i=0;i<n;i++) cin>>record[i].left>>record[i].right;
sort(record,record+n,cmp);
for(section s:record){
if(preLeft==-1){
preLeft=s.left;
result++;
}
else
if(s.right<=preLeft){
preLeft=s.left;
result++;
}
}
cout<<result;
return 0;
}
区间不相交问题的一般思路:将这n个区间按照左端点从大到小排序,若左端点相同,则右端点小的排在前面。依次取区间,使用一个变量记录先前区间的左边界,当下一个区间右边界小于等于先前区间的左边界时,加入该区间。
- 输入区间个数N,接着输入N个闭区间,区间左边界在前右边界在后。输出想要使每个区间都至少存在一个点所要使用的点的最少个数
样例输入
4
1 3
2 4
3 5
6 7
样例输出
2
#include<iostream>
#include<algorithm>
using namespace std;
typedef struct section{
int left,right;
}section;
bool cmp(section a,section b){
if(a.left!=b.left) return a.left>b.left;
else return a.right<b.right;
}
int main(){
int n,result=0,preLeft=-1;
cin>>n;
section record[n];
for(int i=0;i<n;i++) cin>>record[i].left>>record[i].right;
sort(record,record+n,cmp);
for(section s:record){
if(preLeft==-1){
preLeft=s.left;
result++;
}
else
if(s.right<preLeft){
preLeft=s.left;
result++;
}
}
cout<<result;
return 0;
}
区间选点问题一般思路:将这n个区间按照左端点从大到小排序,若左端点相同,则右端点小的排在前面。依次取区间,使用一个变量记录先前区间的左边界,当下一个区间右边界小于(区间相交问题是小于等于)上一个区间左端点时,说明点数需要加一了。
5.二分
- 二分查找
#include<iostream>
using namespace std;
int arr[]={0,1,2,3,4,5,6,7,8,9,10};
int main(){
int left=0,right=10,mid=(left+right)/2,target=11;
while(arr[mid]!=target){
if(arr[mid]>target) right=mid-1;
else left=mid+1;
if(left>right) {mid=-1; break;}
mid=(left+right)/2;
}
cout<<mid<<endl;
return 0;
}
- 给定整数n,m分别代表木棒数量,之后给定n正整数,代表n根木棒的长度。要求切割n根木棒后得到的相同长度的m根木棒数量,求这些长度相同的木棒的最大可能长度
样例输入
3 7
10 24 15
样例输出
6
代码
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> v;
int f(int len){
int result=0;
for(int i:v)
result+=i/len;
return result;
}
//基本思路,求出不能得到m根木棒的最小长度left,然后把left-1即可
int main(){
int n,m,temp;
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>temp;
v.push_back(temp);
}
sort(v.begin(),v.end());
int left=0,right=v[n-1],mid=(left+right)/2;
while(right>left){
if(f(mid)>m) left=mid; //若当长度mid时可得到的木棒数大于m,说明left一定大于mid
else if(f(mid)<m) right=mid-1;//若当长度mid时可得到的木棒数小于m,说明left一定小于mid
else left=mid+1; //若当长度mid时可得到的木棒数等于m,说明left一定大于等于mid
mid=(left+right)/2;
}
//因为最后依次迭代right=left确定的left值,有两种情况,这个left代表的长度可能满足条件也可能不满足条件,所以需要判断一下
f(left)>=m? cout<<left<<endl : cout<<left-1<<endl;
return 0;
}
- 快速幂
思路:
//a为底数,b为指数
long long pow(long long a,long long b){
if(b==0) return 1;
if(b%2==1) return a*pow(a,b-1);
else{
long long temp = pow(a,b/2);
return temp*temp;
}
}