《算法笔记》第四章C++解题记录


1.排序

  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;
    }
}
  1. 简单插入排序
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;
    }
}
  1. 结构体排序,使用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.散列

  1. 自编小题:输入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;
}
  1. 字符串哈希函数(字符串中只允许有大小写字母与数字)
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.递归

  1. 自编小题:输入给定的数字个数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
  1. 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.贪心

  1. PAT乙级1020
#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;
}
  1. PAT乙级1023
#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;
}
  1. 输入区间个数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个区间按照左端点从大到小排序,若左端点相同,则右端点小的排在前面。依次取区间,使用一个变量记录先前区间的左边界,当下一个区间右边界小于等于先前区间的左边界时,加入该区间。

  1. 输入区间个数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.二分

  1. 二分查找
#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;
}
  1. 给定整数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;
}
  1. 快速幂
    思路:在这里插入图片描述
//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;
    }
}

6.二指针

  1. 快排代码

7.其他高效技巧与算法


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值