入门c++刷题思考随笔
1.L2-002 链表去重 关于伪-倒索引的实现
(题目如下)
//给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉。即对每个键值 K,只有第一个绝对值等于 K 的结点被保留。同时,所有被删除的结点须被保存在另一个链表上。例如给定 L //为 21→-15→-15→-7→15,你需要输出去重后的链表 21→-15→-7,还有被删除的链表 -15→15。
//输入格式:
//输入在第一行给出 L 的第一个结点的地址和一个正整数 N(≤10
//5
//,为结点总数)。一个结点的地址是非负的 5 位整数,空地址 NULL 用 −1 来表示。
//随后 N 行,每行按以下格式描述一个结点:
突破点:因为链表的节点包括 :此节点的地址,此节点数据,下一个节点的地址;我们需要遍历乱序的输入链表,因此通过id_to_nod[id]=0,1,2...n(index),来遍历;在判断函数里面,每次会输入id ,通过(输入的)id得到间接存放节点的数组编号index,再通过index访问到对应节点的值、地址
易错点:我们在输出的时候,结构是这样的:(节点地址) (值) (下一个地址)
00100 21 23854
23854 -15 99999
99999 -7 -1
00000 -15 87654
87654 15 -1
考虑到我们输出的节点是按照去重后的节点,而且并没有像真实链表一样修改ptr的链接,是通过输出的方式呈现;方式如下
*注意:修改后的节点顺序是排序好的,按照顺序输出就可以,只需要注意输出格式
(先输出此节点地址 、此节点值)=>进入判断刚才输出的节点不是最后一个节点?(i<num.size()-1)
是:输出结尾的-1;
否:输出下一个节点的地址 *注意 这里是下一个节点的,不是这个节点的下一个地址,因为现在的node是被修改过的
小结:记得通过数据本身去遍历检查,而不是靠数组的index
00x00的输出使用printf而非cout %05d...
2.数列旋转的实现方式
「a.表达式赋值
b.中心偏移量」
//P4924:
//"Scarlet 最近学会了一个数组魔法,她会在 n×n 二维数组上将一个奇数阶方阵按照顺时针或者逆时针旋转 90
//首先,Scarlet 会把 1 到 n
//2
// 的正整数按照从左往右,从上至下的顺序填入初始的二维数组中,然后她会施放一些简易的魔法。
//Scarlet 既不会什么分块特技,也不会什么 Splay 套 Splay,她现在提供给你她的魔法执行顺序,想让你来告诉她魔法按次执行完毕后的二维数组。
//输入格式
//第一行两个整数 n,m,表示方阵大小和魔法施放次数。
//接下来 m 行,每行 4 个整数 x,y,r,z,表示在这次魔法中,Scarlet 会把以第 x 行第 y 列为中心的 2r+1 阶矩阵按照某种时针方向旋转,其中 z=0 表示顺时针,z=1 表示逆时针。
//输出格式
//输出 n 行,每行 n 个用空格隔开的数,表示最终所得的矩阵。
a: 基础过程:先根据用户输入中心数组坐标,减去对应方阵变长的一半,得到将变化的方阵的左上角,随后保存,另外造一个同样的方阵 通过规律观察得到
change[j][len-i-1] = temp[i][j];
再 num[s_x+i][s_y+j]=change[i][j];
b.把旋转看作坐标变换,每个点相对于旋转中心有偏移量 (dx, dy),旋转后偏移量变为 (dx', dy'),然后加回中心坐标。
dx = x - cx 行方向的偏移
dy = y - cy 列方向的偏移
代码实现:
for(int i=0;i<len;i++){
for(int j=0;j<len;j++){
// 相对于子矩阵中心的偏移(中心在 (r, r))
int dx=i-r;
int dy=j-r;
int ndx=dy;
int ndy=-dx;//这是顺时针的变化
int nx=r+ndx;
int ny=r+ndy;//新的偏移量;
//temp[i][j]=num[nx][ny];错误做法 应该是temp里面选位置放
res[nx][ny]=temp[i][j];
}
}
//要把子矩阵放回原来的num矩阵,用top+i来实现区域的len编程的遍历
for(int i=0;i<len;i++){
for(int j=0;j<len;j++){
rew[top+i][left+j]=res[i][j];
}
}
//这类题还需要注意的是题目老是以‘1’为基,在传参的时候要‘-1’转换,同时注意输出方式是0基还是1基
3.三种多行字符串的输入方式:cin>>
char ch>>类型
set
string temp;
char ch;
while(cin.get(ch)){<-----------------一个字符一个字符地读取
if(isalpha(ch)){<------------------避免读取到标点符号的关键,并不是普通的检验
temp+=tolower(ch);//一般竞赛的题会格式化全部转小写(这里是“每输入一个字符,改一次字符”,后另外的每个字符串遍历改小写有区别)
}else{
if(!temp.empty()){<-----------.empty()判断是否为空
word.insert(temp);
temp.clear();
}
}
}
if(!temp.empty()){
word.insert(temp);<----------------如果是最后一次,假如最后还有剩余,则补上;
}
每次string类型读取
string s;
vector
while(cin>>s){//<--------------cin特性会跳过空格只读取string类型
if(s=="#"){break;}
word.push_back(s);
}
string line;
set
while(getline(cin,line)){
stringstream ss(line);<----------把line变成流
string temp;
while(ss>>temp){//<------------自动以空格分割了
for(auto &it:temp){
if(isalpha(it)){//<--------看似无用实则神来之笔只获取了字母
it=tolower(it);
}
}
if(!temp.empty()){
res.insert(temp);
//temp.clean();//<---------为什么不用清空:因为while (ss >> temp) { 每次循环,ss >> temp 会覆盖 temp 的内容
}
}
}
4.总结了一些迭代器的内容,比如在处理数组的时候应该注意到底是返回的到底是最后一个元素的位置还是后面一个的位置
.begin() 返回第一个元素的地址(广义?)可以通过*item.begin()解获得值
.front() 直接返回第一个元素的值 >不可解
.rend() 第一个元素前面的地址 >不可解
.rebgin() 最后一个元素的地址 >可解
.subset( int start , int len )截取从包括start开始长度为len长度的字符串,返回类型是string类型
upper_bound( item.begin() , item.end() , int num ) 返回容器内第一个大于num的迭代器,指定范围内,可以用于贪心的时候寻找最优
c++相对于c的字符串不同比较函数
s.compare(s2) s s2都是string类型
返回值 0 全部相等
<0 则s<s2
来自luogo的算法1.1基础,天梯赛L1-L2一些小题,Uva的一些入门,第一次写,还不知道怎么排版,也就先总结到这里吧,如果内容有明显基础错误还请大佬指出,非常感谢!
posted on 2026-03-28 00:17 tintin7790 阅读(42) 评论(0) 收藏 举报
浙公网安备 33010602011771号