DS代码 仅仅作为一个记录
链表
真题
2013
算法思想
p,q分别指向A,B。若p -> data > q -> data q指针后移,p -> data < q -> data p指针后移并且删除原p结点,p -> data = q -> data,p结点尾插法插入到A后面,实现倒序,并且后移pq指针,直到遍历完其中一个链表,最后删除A中后面多余的结点,返回头节点A。
- 时间复杂度:O(N+M),对链表每个节点遍历了一次;
- 空间复杂度:O(1),只使用了常量的空间。
原题版本
// 取两个递增链表的交集,返回递减链表
// 如果有重复元素可以设置一个int型变量记录两次插入的结点数值是否相同
LinkList GetCommon(LinkList A, LinkList B){
LNode *p = A -> next, *q = B -> next, s = NULL;
A -> next = NULL; //清空链表
while(p && q){// data比较,判断是否为交集中的元素,偏小则后移
if(p -> data < q -> data){
s = p -> next; //删除A中不是交集中的结点
free(p);
p = s;
}
else if(p -> data < q -> data){
q = q -> next //返回A,不对B处理
}
else{
s = p -> next; //头插法插到A后面,倒序
p -> next = A -> next;
A -> next = p;
p = s;
}
while(p){
s = p -> next; //删除A中其他结点
free(p);
p = s;
}
}
return A;//带头节点
}
改进版本
// 取两个递增链表的交集,返回递减链表
// 如果有重复元素可以设置一个int型变量记录两次插入的结点数值是否相同
LinkList GetCommon_New(LinkList A, LinkList B){
LNode *p = A -> next, *q = B -> next, s = NULL;
A -> next = NULL; //断开链表用于插入
int oldn = -1, newn = -1;
while(p && q){// 判断是否为交集中的元素
if(p -> data < q -> data || p -> data == oldn){ //与上次加入的结点重复时也删除
s = p -> next; //删除A中不是交集中的结点
free(p);
p = s;
}
else if(p -> data < q -> data){
q = q -> next //返回A不对B处理
}
else{
oldn = p -> data;
s = p -> next; //头插法插到A后面倒序
p -> next = A -> next;
A -> next = p;
p = s;
}
while(p){
s = p -> next; //删除A中其他结点
free(p);
p = s;
}
}
return A;//带头节点
}
2014
算法思想
自己先想到的:首先遍历链表得到最后一个奇编号结点p,然后遍历链表利用pq指针将偶数序号结点头插法插入到p结点之后,直到被删除结点的前驱节点指向p时(原链表已完成操作)结束返回L, 若非结点数小于3无需操作直接返回
狮子的:不同点,把偶数结点尾插到新申请结点B的后面,操作完成后拼接AB链表
时间复杂度o(n):进行一次or两次遍历链表
空间复杂度:O(1):只使用了常量的空间。
实现代码自己的
//奇数序号结点倒序尾插到偶数结点之后
LinkList DoubleReverse(LinkList L){
LNode *p = L -> next, *q = L, *s = NULL, *last;
while(p -> next -> next){ //找到最后一个奇数结点
p = p -> next -> next;
}
last = p;
while(q -> next -> next){ //判断未遍历结点数量
s = q -> next; //把偶数结点移出链表
if(s != last){ //判断是否完成插入
q = s -> next;
s -> next = q -> next;
q -> next = p -> next; //头插法加入到链表的尾部
p -> next = q;
p = q;
q = s -> next;
}
else{
break;
}
}
return L;
}
狮子的
LinkList fun(LinkList A){
LinkList p = A->next;
if(!p->next){return A;}
LinkList q = p->next; /* p 指向 A 的第一个结点 */
LinkList B= (LinkList) malloc(sizeof(LNode) );
B->next = NULL; /* 创建链表 B */
while (p&&q)
{
p->next = q->next;
q->next = B->next;
B->next = q;
if(p->next){
p=p->next;
q=p->next;
}else{break;}
}
p->next = B->next; /* A 后接 B */
free(B);
reruen A;
}
2015
算法思想
使用p指针遍历链表,用max指针指向本次遍历data最大的结点,遍历完成后将此结点头插法到B后面,多次重复步骤直到L的next为空,返回B即为从小到大排序的链表。
- 时间复杂度o(n2)o(n^2)o(n2)空间复杂度o(1)
实现代码
// 链表简单快速排序从小到大
LinkList ListSort(LinkList L){
LinkList B = (LinkList)malloc(sizeof(LinkList));
B -> next = NULL;
LNode *pre = L, *p = L -> next;
LNode *max = L -> next, *maxpre = L;
while(L -> next){
pre = L, p = L -> next;
max = L, maxpre = L -> next;
while(p){
if(p -> data > max -> data){
max = p;
pre = maxpre;
}
p = p -> next;
pre = pre -> next;
}
maxpre -> next = max -> next;
max -> next = B -> next;
B -> next = max;
}
L -> next = B -> next;
free(B);
return L;
}
2016
算法思想
遍历链表同时创建一个新的头节点B,若遍历当前结点和B中结点重复(此时也对B进行一次遍历判断重复,利用int变量n记录是否重复)则删除,不重复则插入到B后面,直到原链表为空。
狮子的:遍历到当前结点时,对之前每一个结点进行遍历,如果出现重复则删除当前结点,跳出循环开始遍历下一个结点(狮子代码里面没有跳出,遍历了全部),直到遍历结束,非头节点的节点数小于2时直接返回头节点。
时间复杂度o(n^2)
空间复杂度o(1)
实现代码
// 删除不排序链表的重复结点,重复只保留一个
LinkList DelReElem(LinkList A){
LNode *q = A -> next;
LinkList B = (LinkList)malloc(sizeof(LinkList));
LNode *s = B;
int n = 1; //记录是否为重复结点
B -> next = NULL;
while(A -> next){// 对链表结点依次遍历
s = B;
while(s){
s = s -> next;
if(q -> data == s -> data){// 重复结点删除
A -> next = q -> next;
q = q -> next;
n = 0
continue;
}
}
if(n == 1){ // 不重复结点插入到B后
A -> next = q -> next;
q -> next = B -> next;
B -> next = q;
q = A -> next;
}
}
A -> next = B -> next;// 拼接到原头指针,返回A
free(B);
return A;
}
狮子的
void del(LinkList L)
{
LinkList p=L->next,q=NULL,pre=NULL;
if(!p){return;}
while(p){
//对于每个节点p,都要将链表里的每个节点遍历一遍确保无重复
pre=p;q=p->next;//pre保存q的前驱
while(q)
{
if(p->data==q->data)
{ //摘下q,free掉
pre->next=q->next;
free(q);
q=pre->next;
}
else{
pre=pre->next;
q=q->next;
}
}
p=p->next;
}
}
2017
算法思想
狮子申请了一个结点,好像不太好 头插方便逆置(思想如图)
时间复杂度on,空间复杂度o1 别忘记写时间和空间复杂度
实现代码
题目:两个递减链表合并为一个递增的链表,使用原结点操作

狮子的
LinkList Merge(LinkList A,LinkList B)
{
LinkList p=A->next,q=B->next,s=NULL;
LinkList C=(LinkList)malloc(sizeof(LNode));
C->next=NULL;
while(p&&q){
if(p->data==q->data)
{
s=p;
p=p->next;
s->next=C->next;
C->next=s;
s=q;
q=q->next;
free(s);
}
else{
if(p->data>q->data)
{
s=p;p=p->next;
}
else{
s=q;q=q->next;
}
s->next=C->next;
C->next=s;
}
}
while(p){
s=p;p=p->next;
s->next=C->next;
C->next=s;
}
while(q){
s=q;q=q->next;
s->next=C->next;
C->next=s;
}
return C;
}
2018
算法思想
实现代码
2019
算法思想
实现代码
2020
算法思想
实现代码
2021
算法思想
实现代码
2022
算法思想
实现代码
基础代码
链表倒序
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *pre = nullptr, *p = head ,*q;
while(p){
q = p -> next;
p -> next = pre;
pre = p;
p = q;
}
return pre;
}
};
##二叉树
该篇博客探讨了多种链表操作的算法思想,包括取两个递增链表的交集并返回递减链表、奇数序号结点倒序、删除不排序链表的重复结点、合并递减链表等。每种操作都详细阐述了时间复杂度和空间复杂度,并提供了相应的代码实现。
711

被折叠的 条评论
为什么被折叠?



