第四章 阅读程序
第一课 模拟策略
【NOIP2011】(累加)
例:
#include <bits/stdc++.h>using namespace std;int main(){int i,n,m,ans;cin>>n>>m;i=n;ans=0;while (i<=m){ans+=i;i++;}cout<<ans<<endl;return 0;}

答案:× × √ √ B A
解析:
第二课 字符处理
【NOIP2009】(二分字符排序)
例:
#include <bits/stdc++.h>using namespace std;const int maxn=50;void getnext(char str[]){int l=strlen(str),i,j,k,temp;k=l-2;while (k>=0 && str[k]>str[k+1]) k--;i=k+1;while (i<l && str[i]>str[k]) i++;temp=str[k];str[k]=str[i-1];str[i-1]=temp;for (i=l-1;i>k;i--){for (j=k+1;j<i;j++){if (str[j]>str[j+1]){temp=str[j];str[j]=str[j+1];str[j+1]=temp;}}}return ;}int main(){char a[maxn];int n;cin>>a>>n;while (n>0){getnext(a);n--;}cout<<a<<endl;return 0;}

答案:× √ √ √ A B
解析:
第三课 枚举算法
【NOIP2013】(判断字符是否为回文)
例:
#include <bits/stdc++.h>using namespace std;int main(){string str;cin>>str;int n=str.size();bool isPlalindrome=true; // isPlalindrome译为:回文数for (int i=0;i<n/2;i++){if (str[i]!=str[n-i-1]){isPlalindrome=false;break;}}if (isPlalindrome) cout<<"Yes";else cout<<"No";return 0;}

答案:× √ √ √ A B
解析:
【NOIP2013】本题的函数写法
#include <bits/stdc++.h>using namespace std;bool is_Plalindrome(string s){int size=s.size();for (int i=0;i<size;i++){if (s[i]!=s[size-i-1]) return false;}return true;} // 判断回文字符串函数int main(){string str;cin>>str;int n=str.size();if (is_Plalindrome(str)) cout<<"Yes";else cout<<"No";return 0;}
【NOIP2017】(字符串中第一个仅出现一次的字母)
例:
#include <bits/stdc++.h>using namespace std;int main(){int t[256];string s;int i;cin>>s;for (i=0;i<256;i++) t[i]=0;for (i=0;i<s.length();i++) t[s[i]]++;for (i=0;i<s.length();i++){if (t[s[i]]==1){cout<<s[i]<<endl;return 0;}}cout<<"no";return 0;}

答案:× × √ × B B
解析:
![]()
第四课 排序算法
【NOIP2010】(给定两个有序数列,合并成一个新的数列)
例:
#include <bits/stdc++.h>using namespace std;const int SIZE=100;int na,nb,a[SIZE],b[SIZE],i,j,k;int main(){cin>>na;for (i=1;i<=na;i++) cin>>a[i];cin>>nb;for (i=1;i<=nb;i++) cin>>b[i];i=1;j=1;while ((i<=na) && (j<=nb)){if (a[i]<=b[j]){cout<<a[i]<<' ';i++;}else{cout<<b[j]<<' ';j++;}}if (i<=na){for (k=i;k<=na;k++) cout<<a[k]<<' ';}if (j<=nb){for (k=j;k<=nb;k++) cout<<b[k]<<' ';}return 0;}

答案:√ √ × √ A A
解析:
附:归并排序
1.算法介绍
- 归并排序是一种高效的 分治法(Divide and Conquer)排序算法,核心思想:
- 1️⃣ 分解:将数组递归拆分为最小单位(单个元素)
- 2️⃣ 合并:将有序子数组合并为更大有序数组
- ✅ 时间复杂度:最优/平均/最坏均为 O(n log n)
- ✅ 稳定性:稳定排序(相同元素顺序不变)
- ✅ 适用场景:大数据量、链表排序、外部排序
2. 分治思想图解
初始数组: [38, 27, 43, 3, 9, 82, 10]↓ 分解[38, 27, 43] [3, 9, 82, 10]↓ 分解 ↓ 分解[38] [27, 43] [3,9] [82,10]↓ 合并 ↓ 合并[27, 38, 43] [3,9,10,82]↓ 合并[3,9,10,27,38,43,82]
3. 合并操作详解
核心步骤:合并两个有序数组
Left数组: [27, 38, 43] Right数组: [3, 9, 10, 82]Step1: 比较左首(27) vs 右首(3) → 取较小值 3Step2: 比较 27 vs 9 → 取 9Step3: 比较 27 vs 10 → 取 10Step4: 直接追加左数组:[27,38,43]结果:[3, 9, 10, 27, 38, 43, 82]
4. C++ 代码实现
#include <bits/stdc++.h>using namespace std;int arr[7]={38,27,43,3,9,82,10};int brr[7];void merge(int a[],int b[],int l,int mid,int r){// 合并为有序数列int i=l,j=mid+1,k=l;// 从左右两边依次判断较小值进行合并while (i<=mid && j<=r){if (a[i]<=a[j]) b[k++]=a[i++];else b[k++]=a[j++];}while (i<=mid) b[k++]=a[i++];while (j<=r) b[k++]=a[j++];for (int i=l;i<=r;i++) a[i]=b[i];}void mergeSort(int a[],int l,int r){// 分解原数组if (l>=r) return ;// 计算中间值int mid=(l+r)/2;mergeSort(a,l,mid); // 左数列mergeSort(a,mid+1,r); // 右数列// 合并merge(arr,brr,l,mid,r);}int main(){mergeSort(0,9); // 左边界和右边界for (int i=0;i<9;i++) cout<<arr[i]<<' ';return 0;}
输出:3 9 10 27 38 43 82
5. 关键点分析
- 递归深度:共 log₂n 层分解
- 合并成本:每层合并需 O(n) 操作
- 空间复杂度:O(n)(临时数组开销)
- 优化策略:
- 小数组用插入排序减少递归开销
- 避免频繁内存分配(全局复用 temp 数组)
6. 与快速排序对比

7. 可视化演示推荐
(动态理解分解与合并过程)
总结
归并排序以时间换空间,凭借稳定且可预测的性能,成为大规模数据排序的基石算法!
第五课 搜索算法
1.二分查找
1.标准二分查找
代码:
#include <bits/stdc++.h>using namespace std;const int SIZE=105;int n,x,arr[SIZE];int binary_search(int x){int l=0,r=n;while (l+1<r){int mid=(l+r)>>1;if (x==arr[mid]) return mid;else if (x>arr[mid]) l=mid;else r=mid;}return -1;}int main(){cin>>n;for (int i=0;i<n;i++) cin>>arr[i];cin>>x;cout<<binary_search(x);return 0;}
2.给定两个数组,从A数组中找出B数组中的内容,并按从小到大进行排序
代码:
#include <bits/stdc++.h>using namespace std;const int SIZE=10005;int n,m,arr[SIZE],brr[SIZE];int binary_search(int x){int l=0,r=n+1;while (l+1<r){int mid=(l+r)>>1;if (x==arr[mid]) return mid;else if (x>arr[mid]) l=mid;else r=mid;}return 0;}int main(){cin>>n>>m;for (int i=1;i<=n;i++) cin>>arr[i];for (int i=1;i<=m;i++) cin>>brr[i];sort(arr+1,arr+n+1);sort(brr+1,brr+m+1);// 二分查找for (int i=1;i<=m;i++){if (binary_search(brr[i])) cout<<brr[i]<<' ';}return 0;}
3.[USACO05FEB] 进击的奶牛

代码:
#include <bits/stdc++.h>using namespace std;int n,m,a[100005];int main(){cin>>n>>m;for (int i=1;i<=n;i++) cin>>a[i];sort(a+1,a+n+1);int l=0,r=a[n]+1,mid;while (l+1!=r){mid=(l+r)/2;int cnt=1,pre=a[1];for (int i=2;i<=n;i++){if (a[i]-pre>=mid){cnt++;pre=a[i];}}if (cnt>=m) l=mid;else r=mid;}cout<<l;return 0;}
2.深度优先搜索(DFS)
1.引子(给方阵以“右、下、左、上”的顺序填数引入深搜)
#include <bits/stdc++.h>using namespace std;int a[10][10];void f(int x,int y,int k){a[x][y]=k;if (y+1<=4 && a[x][y+1]==0) f(x,y+1,k+1);if (x+1<=4 && a[x+1][y]==0) f(x+1,y,k+1);if (y-1>=1 && a[x][y-1]==0) f(x,y-1,k+1);if (x-1>=1 && a[x-1][y]==0) f(x-1,y,k+1);}int main(){f(1,1,1);for (int i=1;i<=4;i++){for (int j=1;j<=4;j++) cout<<setw(5)<<a[i][j];cout<<endl;}return 0;}
输出:
1 2 3 416 15 14 511 12 13 610 9 8 7
2.深搜的基础框架
#include <bits/stdc++.h>using namespace std;int n,path[410][3];char a[30][30];void print(int k){for (int i=1;i<=k;i++){cout<<'('<<path[i][1]<<','<<path[i][2]<<')';if (i!=k) cout<<"->";}exit(0);}void dfs(int x,int y,int k){path[k][1]=x;path[k][2]=y;a[x][y]='1';if (x==n && y==n) print(k);if (a[x][y-1]=='0') dfs(x,y-1,k+1);if (a[x-1][y]=='0') dfs(x-1,y,k+1);if (a[x][y+1]=='0') dfs(x,y+1,k+1);if (a[x+1][y]=='0') dfs(x+1,y,k+1);}int main(){cin>>n;for (int i=1;i<=n;i++){for (int j=1;j<=n;j++) cin>>a[i][j];}dfs(1,1,1);return 0;}
附:快速排序
#include <iostream>using namespace std;int a[100] = {0};int n;void quickSort(int left,int right){if(left >= right){return;}int i = left;int j = right;int mid = (left + right) / 2;int p = a[mid];while(i <= j){while(a[i] < p){i++;}while(a[j] > p){j--;}if(i <= j){swap(a[i],a[j]);i++;j--;}}if(left < j){quickSort(left,j);}if(i < right){quickSort(i,right);}}int main(){cin >> n;for(int i = 0;i < n;i++){cin >> a[i];}quickSort(0,n - 1);for(int i = 0;i < n;i++){cout << a[i] << " ";}return 0;}
