赵义弘-----补题报告
总述:D系列加强(J组冲奖)的一到四节课的知识概括以及错点分析和代码实现
一.知识梳理
1.排序(冒泡排序,选择排序,插入排序)
排序大家都不陌生,介绍还是要介绍的
1.冒泡排序(稳定的排序)
时间复杂度通常为O(n^2)
代码实现如下
for(int i=1; i<=n-1; i++){//控制比较的轮数for(int j=1; j<=n-i; j++){//控制的是本轮比较的次数if(a[j] < a[j+1]){//比较元素swap(a[j],a[j+1]);//交换这两个元素 } }
}
作用
1、将n个元素从小到大或从大到小排序
2、逆序对的个数(需要交换的次数)
过程
它的工作原理是每次检查相邻两个元素,如果前面的元素与后面的元素满足给定的排序条件,就将相邻两个元素交换。当没有相邻的元素需要交换时,排序就完成了。
经过 次扫描后,数列的末尾 项必然是最大的 项,因此冒泡排序最多需要扫描 遍数组就能完成排序。
性质
冒泡排序是一种稳定的排序算法
以上是对冒泡排序更为详细的介绍,可供参考
2.选择排序(不稳定的排序)
时间复杂度与冒泡一致为O(n^2)
代码实现如下
for(int i = 1; i <= n - 1; i++){//确定范围起点 a[i]int index = i;//初始化a[i]~a[n]范围中的最小值下标 for(int j = i + 1; j <= n; j++){//范围剩余元素if(a[j] < a[index]){//有更小的index = j;//更新最小值下标 } } if(i!=index){swap(a[i],a[index]);//确保a[i]存的值最小 }
}
作用
将 个元素从小到大或从大到小排序。
过程
它的工作原理是:从数组 的连续的范围 里,每次找出最值,对整个 数组来说是第小(大)的元素,然后将这个元素与第 个位置上的元素交换。
效果是:让 中 是最值,然后下一个范围变成 重复上述步骤,让 继续存剩余元素中的最值。每次求的是最大值,整体就会从大到小;每次求的是最小值,整体就会从小到大。
性质
选择排序是一种不稳定的排序算法。
以上是对选择排序更为详细的介绍,可供参考
3.插入排序(稳定的排序)
时间复杂度最优解为O(n),不优解为O(n^2)
代码实现如下
for(int i = 2; i <= n; i++){//「未排序」部分int j , key = a[i];//选一个插入到「已排序」部分 for(j = i - 1; j >= 1 && key < a[j]; j--){//遍历「已排序」部分a[j]a[j+1] = a[j];//把a[j]向后移动 } a[j+1] = key;//合适位置放key,插入成功
}
作用
将 个元素从小到大或从大到小排序。
过程
它的工作原理是:将待排列元素划分为「已排序」和「未排序」两部分,每次从「未排序的」元素中拿一个插入到「已排序的」元素中的正确位置。
初始的「已排序」部分,只有一个元素,其余都是「未排序」部分。每次的独立操作都是把一个元素插入到有序数组中,使得有序。
性质
插入排序是一种稳定的排序算法。
以上是对插入排序更为详细的介绍,可供参考
蒟蒻我没有被排序难倒,所以就不为大家展示错点了
2.STL(栈,队列,map,vector,set,priority_queue)
先从栈说起吧
一个容器,特性为先进后出
就像这个弹夹一样,你压进去的子弹最后才打出来
以下为栈的几个常用操作
1. 定义栈
//数组模拟
int sta[100]; //定义栈元素都是int类型
int top = -1;//top表示栈顶元素下标。一开始0下标没放元素,所以再后退一个指向。
//STL
stack<int> sta;//定义栈元素都是int类型
2. 入栈x元素
//数组模拟
top++;//指针先移动到下一个位置
sta[top] = x;
//STL
sta.push(x);
3. 判断栈是否为空
//数组模拟
top == -1 //栈空
//STL
sta.empty() == 1//栈空
4. 输出栈顶元素
//数组模拟
cout << sta[top]; //top指向栈顶元素
//STL
cout << sta.top();
5. 出栈
//数组模拟
top--; //栈指针往后移动
//STL
sta.pop();
------------------------------------------------------这里是分割线------------------------------------------------------
知识点就先梳理到这(后续补上,蒟蒻我偷点小懒)
二.错点分析
我的绝大多数错误都出在了STL这一块
先看看第一道题
最近的一对
题目描述
给定一个长度为n的数组a。
假设对于a数组的下标 i,j,找出满足 1≤i<j≤n1≤i<j≤n ,且 ai==ajai==aj ,且 j−ij−i 最小。输出aiai
如果有多个答案,输出最小的 i 对应的aiai 。
输入描述
第一行:输入一个正整数n,表述如题。
第二行:输入n个整数,表示a数组。
输出描述
输出符合条件的最小的aiai,如果没有答案,则输出No
。
输入样例
10
19 13 11 19 11 5 6 3 4 3
输出样例
11
错误代码如下
时间过的有点长错因忘了是啥了,蒟蒻对不起大家,下面直接呈现正确代码了
任意进制转换
一道比较常见的题,在luogu上也能搜到(p1143)
这道题错因主要是没有判断字符是否为0
代码如下
#include<bits/stdc++.h>
#define endl '\n'
typedef long long ll;
const int N=1e6+5;
ll n,t,m,x,a[N],d,ans,cnt;
using namespace std;
int main(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);string s;cin>>n>>s;int ten=0;for(int i=0;i<s.size();i++){ten=ten*n;if(isdigit(s[i])) ten=ten+s[i]-'0';else ten=ten+s[i]-'A'+10;}cin>>n;stack<int> st;if(ten==0) cout<<0;while(ten){st.push(ten%n);ten=ten/n;}while(!st.empty()){if(st.top()<10) cout<<st.top();else cout<<char(st.top()+'A'-10);st.pop();}return 0;
}
代码是肯定AC了
三.代码中所使用的特殊语句
1.
#define endl '\n'
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
在输入输出的数据过大时我们可以关闭同步,代码如上
2. 一些is开头的函数
isalpha()用来判断一个字符是否为字母
isalnum()用来判断一个字符是否为数字或者字母,也就是说判断一个字符是否属于a~ z||A~ Z||0~9
isdigit() 用来检测一个字符是否是十进制数字0-9
islower()用来判断一个字符是否为小写字母,也就是是否属于a~z
isupper()和islower相反,用来判断一个字符是否为大写字母
行了,差不多就这些了
蒟蒻请大家帮个忙,如果有luogu号的话可以去骚扰一下LN老师