2020考研复试上机学习笔记


前言

复试时存在有道云的笔记,整理一下,将来还能用。


第二章 暴力求解

2.1 枚举

2.1.3 输入格式

函数格式:

include <iostream>
#include <cstdio>
#include <algorithm>//算法包

using namespace std;

int main(){
    
    return 0;
}

1.多组输入,未知组数

#include "stdio.h"
int main(){
    int a,b;
    while(scanf("%d%d",&a,&b) != EOF){//多组输入,未知组数
        printf("%d\n",a+b);
    }
    return 0;
}

2.多组输入,指定组数

#include "stdio.h"
int main(){
    int a,b,n;
    scanf("%d",&n);
    while(n--){//多组输入,指定组数
        scanf("%d%d",&a,&b);
        printf("%d\n",a+b);
    }
    return 0;
}

3.多组输入,指定输出停止

#include "stdio.h"
int main(){
    int a,b;
    while(scanf("%d%d",&a,&b) != EOF){//多组输入
        if(a == 0 && b == 0){//指定输出停止
            break;
        }
        printf("%d\n",a+b);
    }
    return 0;
}

2.2 模拟

图形模拟
日期模拟
其他模拟

2.2.1 图形排版1:【例题2.4】输出梯形

输入一个高度h,输出一个高为h,上底边为h的梯形。
思路:1.行列数 2.空格数,星号数

#include "stdio.h"
int main(){
    int h;
    while(scanf("%d",&h) != EOF){
        int row = h;
        int col = h + 2 * (h-1);
        for(int i = 0;i<row;i++){//控制行数
            for(int j = 0;j<col;j++){
                if(j<col - (h+2*i)) {
                    printf(" ");
                }else{
                    printf("*");
                }
            }
            printf("\n");
        }
    }
    return 0;
}

2.2.1 图形排版2:【例题2.5】叠筐

题目描述:把一个个大小差一圈的筐叠上去,是的从上往下看时,边框花色交错。

2.2.2 日期问题1:【例题2.6】今年的第几天

/*
 * 输入年、月、日,计算该天是本年的第几天。
 */
#include "stdio.h"
int a[2][13]={{0,31,28,31,30,31,30,31,31,30,31,30,31},
              {0,31,29,31,30,31,30,31,31,30,31,30,31}};
bool IsLeapYear(int year){
    if((year%4==0&&year%100!=0)||(year%400==0)){
        return 1;
    }else{
        return 0;
    }
}
int main(){
    int year,month,day;
    while(scanf("%d %d %d",&year,&month,&day) != EOF){
        int number = 0;
        int row = IsLeapYear(year);
        for(int i = 0;i<month;i++){
            number += a[row][i];
        }
        number+=day;
        printf("%d\n",number);
    }
}

2.2.2 日期问题2:【例题2.7】打印日期

/*
 * 给出年份m和一年中的第n天,算出第n天是几月几号。输入:2000 3。输出:2000-01-03
 */
#include "stdio.h"
int a[2][13]={{0,31,28,31,30,31,30,31,31,30,31,30,31},
              {0,31,29,31,30,31,30,31,31,30,31,30,31}};
bool IsLeapYear(int year){
    if((year%4==0&&year%100!=0)||(year%400==0)){
        return 1;
    }else{
        return 0;
    }
}
int main(){
    int year,number;
    while(scanf("%d%d",&year,&number) != EOF){
        int month = 1,day;
        int row = IsLeapYear(year);
        while(number-a[row][month]>0){
            number=number-a[row][month];
            month++;
        }
        day = number;
        printf("%d-%02d-%02d",year,month,day);//%02d意思是输出两位整数,不足则补0
    }
}

2.2.3 其他模拟:【例题2.10】手机键盘的按键时间

#include <iostream>
#include <cstdio>
using namespace std;//c++全局命名空间

int keytab[26]={1,2,3,1,2,3,1,2,3,1,2,3,1,
                2,3,1,2,3,4,1,2,3,1,2,3,4};
int main(){
    string str;//c++才有字符串
    while(cin >> str){//注意字符串输入格式
        int time = 0;
        for(int i = 0 ;i<str.size();i++){
            time += keytab[str[i] - 'a'];
            if((i != 0)&&(keytab[str[i]-'a']-keytab[str[i-1]-'a'] == str[i] - str[i-1])){
                //同组等待
                time+=2;
            }
        }
        printf("%d\n",time);
    }
    return 0;
}

第三章 排序与查找

3.1 排序

sort函数:first起始位置,last终止位置,comp比较函数(默认从小到大排序)

排序:1.内定义数据类型 。 2.自定义数据类型。

排序算法的特性:
线性排序—计数排序
逆序数对(一个序列中前面的数大于后面的数,称他为逆序数)—归并排序
第K大数—快速排序

线性排序:O(nlogn)(下限) ---- 基于比较
O(n) ----给定范围

3.1.1 排序【例题3.1】

题目:对输入的n个数进行排序并输出
输入:输入的第一行包括一个整数n。接下来的一行包括n个整数。
输出:可能有多组测试数据,对于每组数据,输出排序后的n个整数,每个数后面都有一个空格。每组测试数据的结果占一行。
样例输入:
4
1 4 3 2
样例输出:
1 2 3 4

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;
int arr[100];

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        for(int i = 0;i < n ;i++){
            scanf("%d",&arr[i]);
        }
        sort(arr,arr+n);//默认升序排列
        for(int i = 0 ; i < n ;i++){
            printf("%d ",arr[i]);
        }
    }
    return 0;
}

3.1.2 排序【例题3.2】成绩排序

#include <iostream>
#include <cstdio>
#include <algorithm>//算法包

using namespace std;

struct Student{//定义学生类
    int number;
    int score;
};

Student arr[100];//结构体数组

bool compare(Student x,Student y){//自定义sort的compare方法
    if(x.score==y.score){
        return x.number<y.number;//如果成绩相同,学号小的在前
    }else return x.score<y.score;//成绩升序排序
}

int main(){
    int n ;
    scanf("%d",&n);
    for(int i = 0 ;i < n; i++){
        scanf("%d%d",&arr[i].number,&arr[i].score);
    }
    sort(arr,arr+n,compare);//sort(开始地址,结束地址,排序方法)
    for(int i = 0 ;i < n;i++){
        printf("%d %d\n",arr[i].number,arr[i].score);
    }
    return 0;
}

3.1.3 排序【习题3.2】整数奇偶排序

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

int arr[10];

bool compare(int x,int y){//x,y有四种奇偶可能,找到内部的排序关系
    if(x%2==1 && y%2==1){
        return x<y;
    }else if(x%2==0 && y%2==0){
        return x<y;
    }else if(x%2==1 && y%2==0){
        return true;//x就是应该在y的前面
    }else if(x%2==0 && y%2==1){
        return false;//x不应该在y的前面
    }
}

int main(){
    while(scanf("%d",&arr[0]) != EOF){//多组输入,当第一个数存在时,继续输入给数组
        for(int i = 1;i<10;i++){
            scanf("%d",&arr[i]);
        }
        sort(arr,arr + 10,compare);
        for(int i = 0; i<10;i++){
            printf("%d ",arr[i]);
        }
        printf("\n");
    }
    return 0;
}

3.1.4 排序(4)前m大的数

给n个整数,按从小到大的顺序输出其中前m大的数。

/*
 * 给n个整数,按从小到大的顺序输出其中前m大的数
 * input:第一行有两个数n,m(0<n,m<1000000),第二行包含n个各不相同,且都处于区间[-500000,500000]的整数
 * output:对每组测试数据按从小到大的顺序输出前m大的数
 * 样例输入:
 * 5 3 
 * 3 -35 92 213 -644
 * 样例输出:
 * 213 92 3
 */
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;
const int MAXN = 1e6 + 10;//const静态变量。1e6=1*10^6
const int R = 5e5;//5e5=5*10^5

int arr[MAXN];//存储数字
int number[MAXN];//辅助数组,记录出现的次数,类似哈希表

int main(){
    int n,m;
    while(scanf("%d%d",&n,&m) != EOF){
        memset(number,0,sizeof(number));//数组全部赋值0或-1,在cstring类中
        for(int i = 0; i < n ; i++){
            scanf("%d",&arr[i]);
            number[arr[i] + R]++;//数字是辅助数组的下标(因为下标没有负数,所以平移)
        }
        //数组排序
        int index = 0;
        for(int i = 0;i<MAXN;i++) {//遍历辅助数组number
            while(number[i]--){//出现的次数,可能有多次,也有可能不出现,则i跳过,但index不增加
                arr[index++] = i - R;//更新数字,index指向的是arr数组的下标
            }
        }
        //从后向前打印m个大数
        for(int i = n-1;i>=n-m;i--){
            if(i == n-m){
                printf("%d\n",arr[i]);
            }else{
                printf("%d ",arr[i]);
            }
        }
    }
    return 0;
}

3.1.5 排序(5)归并排序:输出逆序对

代码1:【归并排序】

/*
 * 归并排序:一直切一半分成两段,最终每段只有一个数字,视为有序。再两两按大小有序合并。
 * 题目:第一行输入待排序数的个数,第二行输入待排序的数,输出按从小到大排序的数。
 */
#include <iostream>
#include <cstdio>

using namespace std;
const int nmax=100;
int arr[nmax];
int temp[nmax];
/* 连接函数:设置临时数组接收有序的合并数列。
 * 三指针i,j,k,i和j比大小,小则放入temp[k]
 * 某段剩余则全放入temp
 * 最后将temp存回arr数组
 */
void Combine(int left,int middle,int right){
    int i = left;//i指向左段第一个将比较数字
    int j = middle + 1;//j指向右段第一个数字
    int k = left;//k用来表明temp待存位置

    while(i<=middle && j<=right){//是并且&&,i和j同时没有到头,则比较
        if(arr[i] <= arr[j]){
            temp[k++] = arr[i++];
        }else{
            temp[k++] = arr[j++];
        }
    }
    while(i<=middle){
        temp[k++] = arr[i++];
    }
    while(j<=right){
        temp[k++] = arr[j++];
    }
    for(int k = left; k <= right;k++){
        arr[k] = temp[k];
    }
    return;
}

void MergeSort(int left,int right){
    if(left<right){//这一段有一个整数以上,还能拆
        int middle = left + ( right - left )/2;//为了防止left+right溢出
        MergeSort(left,middle);//拆分左段
        MergeSort(middle+1,right);//拆分右段
        Combine(left,middle,right);//假设要合并的两段已经有序
    }
    return;
}

int main(){
    int n;
    scanf("%d",&n);
    for(int i = 0; i < n;i++){
        scanf("%d",&arr[i]);
    }
    MergeSort(0,n-1);
    for(int i = 0 ; i<n;i++){
        printf("%d ",arr[i]);
    }
    return 0;
}

题目:POJ1804 逆序对数

/*
 * 归并排序:一直切一半分成两段,最终每段只有一个数字,视为有序。再两两按大小有序合并。
 * 题目:多组输入,第一行输入组数,从第二行开始,先输入待排序的数的个数,同一行后面输入待排序数。
 * 输出:每组的逆序数。
 * 逆序对数:左大右小的数对的个数。已知左右两段都有序,若arr[i]>arr[j],则左段i后所有数都大于arr[j]
 * 则逆序数对为(middle-i+1)
 */
#include <iostream>
#include <cstdio>

using namespace std;
const int nmax=1010;
int arr[nmax];
int temp[nmax];
int number;//整个序列最终的逆序对数

/* 连接函数:设置临时数组接收有序的合并数列。
 * 三指针i,j,k,i和j比大小,小则放入temp[k]
 * 某段剩余则全放入temp
 * 最后将temp存回arr数组
 */
void Combine(int left,int middle,int right){
    int i = left;//i指向左段第一个将比较数字
    int j = middle + 1;//j指向右段第一个数字
    int k = left;//k用来表明temp待存位置

    while(i<=middle && j<=right){//是并且&&,i和j同时没有到头,则比较
        if(arr[i] <= arr[j]){
            temp[k++] = arr[i++];
        }else{
            number += middle - i + 1;//对于一个arr[j]来说,有middle-i+1个逆序对
            temp[k++] = arr[j++];
        }
    }
    while(i<=middle){
        temp[k++] = arr[i++];
    }
    while(j<=right){
        temp[k++] = arr[j++];
    }
    for(int k = left; k <= right;k++){
        arr[k] = temp[k];
    }
    return;
}

void MergeSort(int left,int right) {
    if (left < right) {//这一段有一个整数以上,还能拆
        int middle = left + (right - left) / 2;//为了防止left+right溢出
        MergeSort(left, middle);//拆分左段
        MergeSort(middle + 1, right);//拆分右段
        Combine(left, middle, right);//假设要合并的两段已经有序
    }
    return;
}

int main(){
    int caseNumber;//caseNumber组数
    scanf("%d",&caseNumber);
    for(int current = 1;current <= caseNumber;current++){
        int n;
        scanf("%d",&n);
        for(int i = 0;  i <n;i++) {//当前组的组号current
            scanf("%d", &arr[i]);
        }
        number=0;
        MergeSort(0,n-1);
        printf("组号:%d",current);
        printf("逆序对数:%d\n\n",number);
    }

    return 0;
}

4
4 2 8 0 3
10 0 1 2 3 4 5 6 7 8 9
6 -42 23 6 28 -100 65537
5 0 0 0 0 0

3.1.6 排序(6)快速排序:第k大数

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>

using namespace std;

int arr[100];

int partition(int left,int right){
    int random = round(1.0*rand()/RAND_MAX*(right - left)+left);
    swap(arr[left],arr[random] );
    while(left < right) {
        while (left < right && arr[right] >= arr[left]){
            --right;
        }
        swap(arr[left] ,arr[right]);
        while (left < right && arr[left] <= arr[right]){
            ++left;
        }
        swap(arr[left] ,arr[right]);
    }
    return left;
}

int Quicksort(int left,int right,int k){
        int pos = partition(left,right);
        if(pos == k-1){
            return arr[pos];
        }else if(pos < k-1){
            return Quicksort(pos+1,right,k);
        }else{
            return Quicksort(left,pos-1,k);
        }
}


int main(){
    int n,k;
    scanf("%d",&n);
    for(int i = 0;i<n;i++){
        scanf("%d",&arr[i]);
    }
    scanf("%d",&k);
    int q = Quicksort(0,n-1,k);
    printf("%d\n",q);
    return 0;
}

3.2 查找

3.2.1 顺序查找-O(n)
3.2.2-3 二分查找-O(logn)
(1)自定义
(2)系统自带:
lower_bound:返回大于或等于目标值的第一个位置
upper_bound:返回大于目标值的第一个位置
散列查找-O(1)

3.2.2 二分查找

#include <iostream>
#include <cstdio>
#include <stdio.h>
#include <algorithm>

using namespace std;
int fun(int a[],int n, int x){
    int left = 0;
    int right = n-1;
    while(left<=right) {
        int mid;
        mid = left + (right - left) / 2;
        if (x == a[mid]) {
            return 1;
        } else if (x < a[mid]) {
            right=mid-1;
        } else if (x > a[mid]) {
            left=mid+1;
        }
    }
    return 0;
}
bool cmp(int a,int b){
    return a<b;
}
int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        int a[n];
        for(int i = 0;i < n ;i++){
            scanf("%d",&a[i]);
        }
        sort(a,a+n);
        int x,flag=0;
        scanf("%d",&x);
        flag= fun(a,n, x);
        if(flag == 0){
            printf("no\n");
        }else{
            printf("yes\n");
        }
    }
    return 0;
}

第四章 字符串

4.1 字符串

4.2 字符串处理

4.2.1 字符串遍历:特殊乘法

题目链接

#include <string>
#include <iostream>
#include <cstdio>

using namespace std;

int main(){
    string a,b;
    int sum =0;
    cin >> a >> b;
    for(int i = 0;i < a.size();i++){
        for(int j = 0;j<b.size();j++){
            sum += (a[i]-'0')*(b[j]-'0');
        }
    }
    cout << sum <<endl;
    return 0;
}

4.2.2 字符串加密

题目链接

#include <iostream>
#include <cstdio>
#include <string>

using namespace std;

int main(){
    string str;
    while(getline(cin,str)){
        for(int i = 0;i<str.size();i++){
            if(str[i]>='a'&&str[i]<='z'){
                str[i] = (str[i]-'a'+1)%26 + 'a';//别忘了还要再加上起始
            }else if(str[i]>='A'&&str[i]<='Z'){
                str[i] = (str[i]-'A'+1)%26 + 'A';
            }
        }
        cout << str << endl;
    }
    return 0;
}

简单密码

题目链接

#include <iostream>
#include <cstdio>
#include <string>
#include <string.h>

using namespace std;

int main(){
    string str;
    while(getline(cin,str)){
        if("ENDOFINPUT"==str){
            break;
        }
        getline(cin,str);
        for(int i=0;i<str.size();i++){
            if(str[i]>='A'&&str[i]<='Z'){
                str[i]=(str[i]-'A'+21)%26+'A';
            }
        }
        cout << str << endl;
        getline(cin,str);
    }
    return 0;
}

4.2.3 字符串统计

题目链接

#include <iostream>
#include <cstdio>
#include <string>
#include <string.h>

using namespace std;

int main(){
    string str1,str2;
    while(getline(cin,str1)){
        if(str1 == "#"){
            break;
        }
        getline(cin,str2);
        int num[130];
        memset(num,0,sizeof(num));
        for(int n : str2){
            num[n]++;
        }
        for(char i : str1){
            printf("%c %d\n",i,num[i]);
        }
        getline(cin,str1);
    }
    return 0;
}

【例题4.5】字母统计

题目链接

#include <iostream>
#include <cstdio>
#include <string.h>

using namespace std;
#define max 10000
int main(){
    char str[max];
    int num[128];
    memset(num,0,sizeof(num));
    while(gets(str)){
        for(int i = 0;i<strlen(str);i++){
            if(str[i]>='A'&&str[i]<='Z'){
                num[str[i]]++;
            }
        }
        for(int i = 'A';i<='Z';i++){
            printf("%c:%d\n",i,num[i]);
        }
    }
    return 0;
}

4.3 字符串匹配

4.3.2 字符串匹配(2):数字模式串在数字文本串第一次出现的位置KMP

题目链接

#include <iostream>
#include <cstdio>

using namespace std;

const int MAXN=1000000;
const int MAXM=10000;

int text[MAXN];
int pattern[MAXM];
int nexttable[MAXN];

void getNext(int s[],int len) {
    int j = -1;
    nexttable[0] = -1;
    for (int i = 1; i < len; i++) {
        while (j != -1 && s[i] != s[j + 1]) {
            j = nexttable[j];
        }
        if (s[i] == s[j + 1]) {
            j++;
        }
        nexttable[i] = j;
    }
}

int KMP(int n,int m){
    getNext(pattern,m);
    int j = -1;
    for(int i =0;i<n;i++){
        while(j!=-1&&text[i]!=pattern[j+1]){
            j=nexttable[j];
        }
        if(text[i]==pattern[j+1]){
            j++;
        }
        if(j==m-1){
            return i-j+1;
        }
    }
    return -1;
}

int main(){
    int caseNumber,n,m;
    scanf("%d",&caseNumber);
    while(caseNumber--){
        scanf("%d %d",&n,&m);
        for(int i = 0;i<n;i++){
            scanf("%d",&text[i]);
        }
        for(int i = 0; i<m;i++){
            scanf("%d",&pattern[i]);
        }
        printf("%d\n",KMP(n,m));
    }

    return 0;
}

4.3.2 字符串匹配(2):模式串在文本串中出现的次数

题目链接
在这里插入图片描述

#include <iostream>
#include <cstdio>

using namespace std;

const int MAXN=1000000;
const int MAXM=10000;

char text[MAXN];
char pattern[MAXM];
int nexttable[MAXN];

void getNext(char s[],int len) {
    int j = -1;
    nexttable[0] = -1;
    for (int i = 1; i < len; i++) {
        while (j != -1 && s[i] != s[j + 1]) {
            j = nexttable[j];
        }
        if (s[i] == s[j + 1]) {
            j++;
        }
        nexttable[i] = j;
    }
}

int KMP(char text[],char pattern[]){
    int n = strlen(text),m=strlen(pattern);
    getNext(pattern,m);
    int j = -1,ans=0;
    for(int i =0;i<n;i++){
        while(j!=-1&&text[i]!=pattern[j+1]){
            j=nexttable[j];
        }
        if(text[i]==pattern[j+1]){
            j++;
        }
        if(j==m-1){
            ans++;
            j=nexttable[j];
        }
    }
    return ans;
}

int main(){
    int num;
    scanf("%d",&num);
    while(num--){
        scanf("%s", pattern);
        scanf("%s",text);
        printf("%d\n", KMP(text, pattern));
    }
    return 0;
}

第五章 数据结构一


总结

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值