203.移除链表元素

卡哥题目建议:本题最关键是要理解虚拟头结点的使用技巧,这个对链表题目很重要。

做题思路: 

 1,分为不带头节点的和带(虚拟)头节点的两种情况。

1.1 . 不带头节点就是直接在原链表上删除节点,删第1个节点之后的节点需要改一下指针指向,就是用文字描述,比如删第2个节点,让第1个节点的指向第3个节点,再释放第2个节点。同理,除了第1个有效节点即首节点外,其他节点都是通过前一个节点来删除当前节点,但是首节点没有前1个节点。所以首节点如何删除呢,其实只要将首节点的指针指向,向后移动一位就可以,这样就从链表中删除了一个首节点。

1.2. 带虚拟头节点就是在初始化链表的时候,创建出一个头节点,方便使原链表的所有节点就都可以按照统一的方式进行删除了。因为看 3.1 的思路,需要单独写一段逻辑来处理移除头结点的情况。

在后续代码中 ,使用LinkList,强调这是一个单链表; 使用LNode,强调这是一个节点。

这里的代码模仿了我写的博客:https://www.cnblogs.com/romantichuaner/p/17557080.html,我用C语言写的。根据这个题,作了删除函数的改变。

 1 bool DeleteList(LinkList &L, int val)//删除表L中值为 val 的元素
2 {
3 LNode *p = L->next, *q = L, *s; //L是头节点,L->next是第一个有效节点
4
5 while(p != NULL) //从第一个有效节点开始循环找值为val的节点
6 {
7 if(p->data == val)
8 {//原本顺序 p,q,s
9 s = p; //找到要删除的节点的话,就先用节点s保存p ,
10 p = p->next;//更改p的指向,在删除思路里说过,现在顺序 s,q,p
11 q->next = p;//q的指向也要记得改
12 free(s); //释放原来p所在的节点,只不过现在变成了s
13 }
14 else
15 {
16 q = p;//没有找到的话,就依次遍历其他节点,有种交换的感觉
17 p = p->next;
18 }
19 }
20 return true;
21 }

完整代码的函数调用也改变了。

1 case 2: //2,删除数据
2 int val;
3 scanf("%d",&val);
4 DeleteList(L,val);
5 getchar();
6 break;

本题中是把链表中的元素键盘输入的,所以这里我还改了添加函数的调用。

 1 case 1: //1,添加数据
2 printf("请输入元素个数:\n");
3 scanf("%d",&n);
4 printf("请添加元素:\n");
5 for(int i = 1; i <= n; i++)
6 {
7 scanf("%d",&num);
8 InsertList(L,i,num);
9 }
10 printf("数据添加成功!\n");
11 getchar();
12 break; 

综上,本题完整代码以及拓展的一些操作代码如下:

  1 #include <stdio.h>
2 #include <malloc.h>
3 typedef struct LNode{ //定义单链表结点类型 //这种方式代码可读性更强
4 int data;//每个节点存放一个数据元素
5 struct LNode *next;//指针指向下一个节点
6 }LNode, *LinkList; //LNode 是struct LNode 的别名,LinkList是struct LNode *的别名,指针指向整个结构体
7 bool InitList(LinkList &L) //初始化一个单链表(带头结点)
8 {
9 L = (LNode *)malloc(sizeof(LNode)); //分配一个头节点,malloc函数强调返回是一个节点(LNode *),如果单链表有头节点,则头指针指向头节点,即 LinkList L = (LNode *)malloc(sizeof(LNode)); 等号有指向作用
10 if(L == NULL) //内存不足,分配失败,就没有创建出单链表,因为已经分配了一个节点,所以只能内存不足的原因,空表是没有节点
11 return false;
12 L->next = NULL;//目前只有一个头节点,头节点之后暂时还没有节点
13 return true;
14 }
15 bool InsertList(LinkList &L, int i, int e) //在第 i 个位置插入元素 e (带头结点)
16 {
17 if(i < 1) //只能在头结点之后插入,头结点是第0个,之后是第1个
18 return false;
19 LNode *p; //LNode * 强调这是一个结点,声明一个结点,表示指针p指向当前找到的结点
20 p = L; //L是指向头结点的头指针,再把刚开始的指针p指向L,表示目前的指针p指向头结点
21 int j = 0;//记录当前p指向的是第几个结点,从头结点0开始
22 while(p!= NULL && j < i - 1) //循环找到第 i-1 个结点,j = i-1,不进入循环,内存满了,不进入循环
23 {
24 p = p->next; //p指向下一个结点
25 j++;
26 }
27 if(p==NULL) //i值不合法,如果有4个结点,那i不能等于6,因为 p = p->next,在第5个位置之后满了,p指向NULL,下一步p->next出错了,根本找不到表的某个位置
28 return false;
29 LNode *s = (LNode *)malloc(sizeof(LNode));//创建一个节点,这个节点的数据域就是e
30 s->data = e;
31 s->next = p->next; //自己画图理解,一开始p后的节点不是s,这里让p的下一个节点变成了在s的下一个节点
32 p->next = s; //将结点s连到p之后
33 return true; //插入成功
34 }
35 void ShowList(LinkList L) //显示
36 {
37 if(L->next == NULL)
38 printf("这是一个空表\n");
39 while(L != NULL)
40 {
41 L = L->next;
42 printf("%d ",L->data);
43 }
44
45 }
46 bool DeleteList(LinkList &L, int val)//删除表L中值为 val 的元素
47 {
48 LNode *p = L->next, *q = L, *s; //L是头节点,L->next是第一个有效节点
49
50 while(p != NULL) //从第一个有效节点开始循环找值为val的节点
51 {
52 if(p->data == val)
53 {//原本顺序 p,q,s
54 s = p; //找到要删除的节点的话,就先用节点s保存p ,
55 p = p->next;//更改p的指向,在删除思路里说过,现在顺序 s,q,p
56 q->next = p;//q的指向也要记得改
57 free(s); //释放原来p所在的节点,只不过现在变成了s
58 }
59 else
60 {
61 q = p;//没有找到的话,就依次遍历其他节点,有种交换的感觉
62 p = p->next;
63 }
64 }
65 return true;
66 }
67 int GetList(LinkList &L, int i)//按位查找,返回第 i 个元素(带头节点)
68 {
69 if(i < 0)//有头节点,头节点是第0个节点,所以查找元素i不能小于0
70 return 0;
71 LNode *p;
72 int j = 0;
73 p = L;
74 while(p != NULL && j < i) //找的是第i个节点,插入那里找的是第i-1 个节点
75 { //如果i大于表的长度,那循环找到的p会指向NULL,不会进入循环体,最后返回NULL
76 p = p->next;
77 j++;
78 }
79 return p->data;
80 } //平均时间复杂度为O(n)
81 int UpdateList(LinkList &L, int i, int num)
82 {
83 if(i < 0)//有头节点,头节点是第0个节点,所以查找元素i不能小于0
84 return 0;
85 LNode *p;
86 int j = 0;
87 p = L;
88 while(p != NULL && j < i) //找的是第i个节点,插入那里找的是第i-1 个节点
89 { //如果i大于表的长度,那循环找到的p会指向NULL,不会进入循环体,最后返回NULL
90 p = p->next;
91 j++;
92 }
93 p->data = num;
94 return p->data;
95 }
96 void Destroy(LinkList &L) //销毁单链表
97 {
98 LNode *p;
99 while(L != NULL)
100 {
101 p = L;
102 L = L->next;
103 free(p);
104 }
105 }
106 void ShowMenu()
107 {
108 printf("************************\n");
109 printf("***** 1,添加数据 *****\n");
110 printf("***** 2,删除数据 *****\n");
111 printf("***** 3,查找数据 *****\n");
112 printf("***** 4,修改数据 *****\n");
113 printf("***** 5,显示数据 *****\n");
114 printf("***** 0,销毁并退出 ***\n");
115 }
116 int main()
117 {
118 LinkList L;//声明一个单链表
119 InitList(L);//初始化函数调用
120 int n = 0;
121 int num = 0;
122 int select = 0; //创建选择输入的变量
123 while (true)
124 {
125 //菜单调用
126 ShowMenu();
127 printf("请输入你的选择\n");
128 scanf("%d", &select);
129 switch (select)
130 {
131 case 1: //1,添加数据
132 printf("请输入元素个数:\n");
133 scanf("%d",&n);
134 printf("请添加元素:\n");
135 for(int i = 1; i <= n; i++)
136 {
137 scanf("%d",&num);
138 InsertList(L,i,num);
139 }
140 printf("数据添加成功!\n");
141 getchar();
142 break;
143 case 2: //2,删除数据
144 int val;
145 scanf("%d",&val);
146 DeleteList(L,val);
147 getchar();
148 break;
149 case 3: //3,查找数据
150 printf("查找的元素是:%d\n",GetList(L,1));
151 getchar();
152 break;
153 case 4: //4,修改数据
154 UpdateList(L,1,0);
155 printf("修改成功!\n");
156 getchar();
157 break;
158 case 5: //4,显示数据
159 printf("单链表的数据有:");
160 ShowList(L);
161 getchar();
162 break;
163 case 0: //0,退出
164 Destroy(L);
165 printf("单链表已销毁!");
166 printf("欢迎下次使用");
167 return 0;
168 break;
169
170 default:
171 break;
172 }
173 }
174 return 0;
175 }

运行结果显示:

707.设计链表

题目链接/文章讲解/视频讲解:https://programmercarl.com/0707.%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8.html

卡哥题目建议: 这是一道考察 链表综合操作的题目,不算容易,可以练一练 使用虚拟头结点

做题思路:

1,先看 题目中的 get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。我们需要找到前 index - 1 个节点。函数名自己一改就行。

 1 int GetList(LinkList &L, int i)//按位查找,返回第 i 个元素(带头节点)
2 {
3 if(i < 0)//有头节点,头节点是第0个节点,所以查找元素i不能小于0
4 return -1;
5 LNode *p;
6 int j = 0;
7 p = L;
8 while(p != NULL && j < i) //找的是第i个节点,插入那里找的是第i-1 个节点
9 { //如果i大于表的长度,那循环找到的p会指向NULL,不会进入循环体,最后返回NULL
10 p = p->next;
11 j++;
12 }
13 return p->data;
14 } //平均时间复杂度为O(n)

函数调用。

1 case 3: //3,查找数据
2 printf("查找的元素是:%d\n",GetList(L,1));
3 getchar();
4 break;

运行结果显示:

2,addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。这个和头插法是一样的,看b站的视频吧

 1 bool List_HeadInsert(LinkList &L)//逆向建立单链表
2 {
3 LNode *s;
4 int x;
5 L = (LNode *)malloc(sizeof(LNode)); //创建头结点
6 L->next = NULL; //初始为空链表,养成好习惯,只要是初始化单链表,都先把头指针指向NULL
7 scanf("%d",&x);
8 while(x != 9999)
9 {
10 s = (LNode *)malloc(sizeof(LNode)); //第10行到第13行代码和后插操作InsertNextNode函数第5行到第10行代码是等同的
11 s->data = x;
12 s->next = L->next;//把新结点插入到头结点之后
13 L->next = s;//更改头指针指向
14 scanf("%d",&x);
15 }
16 return true;
17 }

函数调用。注意要把主函数的初始化函数注释了,因为头插法和尾插法函数里就有初始化的一部分。

1 case 6: //头插法
2 List_HeadInsert(L);
3 getchar();
4 break;

运行结果显示:

3,addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。这个和尾插法是一样的。

 1 LinkList List_TailInsert(LinkList &L) //正向建立单链表
2 {
3 int x; //插入的元素
4 L = (LinkList)malloc(sizeof(LNode));//建立头结点
5 LNode *s, *r = L; //声明结点,s是把插入的元素放在结点s,r为表尾指针,让s,r初始化指向,头结点
6 L->next = NULL; //初始为空链表
7 scanf("%d",&x);
8 while(x != 9999) //输入9999表示结束,任意的一个数字
9 {
10 s = (LNode *)malloc(sizeof(LNode)); //分配插入的结点
11 s->data = x;
12 r->next = s; //在r结点之后插入元素x
13 r = s; //永远保持r指向最后一个结点
14 scanf("%d",&x);
15 }
16 r->next = NULL; //插入数字完后,再把尾结点指针置空
17 return L; //返回链表L
18 } //时间复杂度为O(n)

函数调用。

1 case 7: //尾插法
2 List_TailInsert(L);
3 getchar();
4 break;

运行结果显示:

4,addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val  的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。模仿插入函数。

 1 bool InsertList(LinkList &L, int i, int e) //在第 i 个位置插入元素 e (带头结点)
2 {
3 if(i < 1) //只能在头结点之后插入,头结点是第0个,之后是第1个
4 {
5 List_HeadInsert(L); //头插法
6 }
7
8 LNode *p; //LNode * 强调这是一个结点,声明一个结点,表示指针p指向当前找到的结点
9 p = L; //L是指向头结点的头指针,再把刚开始的指针p指向L,表示目前的指针p指向头结点
10 int j = 0;//记录当前p指向的是第几个结点,从头结点0开始
11 while(p!= NULL && j < i - 1) //循环找到第 i-1 个结点,j = i-1,不进入循环,内存满了,不进入循环
12 {
13 p = p->next; //p指向下一个结点
14 j++;
15 }
16 if(p==NULL) //i值不合法,如果有4个结点,那i不能等于6,因为 p = p->next,在第5个位置之后满了,p指向NULL,下一步p->next出错了,根本找不到表的某个位置
17 return false;
18 LNode *s = (LNode *)malloc(sizeof(LNode));//创建一个节点,这个节点的数据域就是e
19 s->data = e;
20 s->next = p->next; //自己画图理解,一开始p后的节点不是s,这里让p的下一个节点变成了在s的下一个节点
21 p->next = s; //将结点s连到p之后
22 return true; //插入成功
23 }

函数调用。注意:调用之间要把主函数的初始化函数注释打开。

1 case 1: //1,添加数据
2 InsertList(L,1,1);
3 InsertList(L,2,2);
4 InsertList(L,3,3);
5 InsertList(L,4,4);
6 InsertList(L,5,5);
7 printf("数据添加成功!\n");
8 getchar();
9 break;

运行结果显示:

5 ,deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。删除思路和今天的第一道一样。

 1 bool DeleteList(LinkList &L, int i)//删除表L中第 i 个位置的元素,并用e返回删除元素的值。
2 {
3 if(i < 1)
4 return false;
5 LNode *p;
6 p = L;
7 int j = 0;
8 while(p != NULL && j < i - 1) //循环找第 i-1 个节点
9 {
10 p = p->next;
11 j++;
12 }
13 if(p == NULL) //i值不合法,导致第 i-1 个节点根本在表中找不到
14 return false;
15 if(p->next == NULL) //第 i-1 个节点能找到,但是刚好第 i-1 个节点之后已无其他节点(第i个结点和第i+1个节点没有了),那就没有办法把第 i-1 个节点的指向下一个节点的指针指向第 i+1 个节点
16 return false;
17 LNode *q = p->next; //p是第 i-1 个节点,p->next是之后的节点,也是第 i 个节点,令q指向被删除节点
18 p->next = q->next; //将*q 节点从链中断开,重新更改指针p的指向,指向第 i + 1个节点
19 free(q); //释放节s点的存储空间
20 return true;
21 } 

函数调用。

1 case 2: //2,删除数据
2 DeleteList(L,1);
3 getchar();
4 break;

运行结果显示:

完整代码实现:

  1 #include <stdio.h>
2 #include <malloc.h>
3 typedef struct LNode{ //定义单链表结点类型 //这种方式代码可读性更强
4 int data;//每个节点存放一个数据元素
5 struct LNode *next;//指针指向下一个节点
6 }LNode, *LinkList; //LNode 是struct LNode 的别名,LinkList是struct LNode *的别名,指针指向整个结构体
7 bool InitList(LinkList &L) //初始化一个单链表(带头结点)
8 {
9 L = (LNode *)malloc(sizeof(LNode)); //分配一个头节点,malloc函数强调返回是一个节点(LNode *),如果单链表有头节点,则头指针指向头节点,即 LinkList L = (LNode *)malloc(sizeof(LNode)); 等号有指向作用
10 if(L == NULL) //内存不足,分配失败,就没有创建出单链表,因为已经分配了一个节点,所以只能内存不足的原因,空表是没有节点
11 return false;
12 L->next = NULL;//目前只有一个头节点,头节点之后暂时还没有节点
13 return true;
14 }
15 bool List_HeadInsert(LinkList &L)//逆向建立单链表
16 {
17 LNode *s;
18 int x;
19 L = (LNode *)malloc(sizeof(LNode)); //创建头结点
20 L->next = NULL; //初始为空链表,养成好习惯,只要是初始化单链表,都先把头指针指向NULL
21 scanf("%d",&x);
22 while(x != 9999)
23 {
24 s = (LNode *)malloc(sizeof(LNode)); //第10行到第13行代码和后插操作InsertNextNode函数第5行到第10行代码是等同的
25 s->data = x;
26 s->next = L->next;//把新结点插入到头结点之后
27 L->next = s;//更改头指针指向
28 scanf("%d",&x);
29 }
30 return true;
31 }
32 bool List_TailInsert(LinkList &L) //正向建立单链表
33 {
34 int x; //插入的元素
35 L = (LinkList)malloc(sizeof(LNode));//建立头结点
36 LNode *s, *r = L; //声明结点,s是把插入的元素放在结点s,r为表尾指针,让s,r初始化指向,头结点
37 L->next = NULL; //初始为空链表
38 scanf("%d",&x);
39 while(x != 9999) //输入9999表示结束,任意的一个数字
40 {
41 s = (LNode *)malloc(sizeof(LNode)); //分配插入的结点
42 s->data = x;
43 r->next = s; //在r结点之后插入元素x
44 r = s; //永远保持r指向最后一个结点
45 scanf("%d",&x);
46 }
47 r->next = NULL; //插入数字完后,再把尾结点指针置空
48 return true; //返回链表L
49 } //时间复杂度为O(n)
50 bool InsertList(LinkList &L, int i, int e) //在第 i 个位置插入元素 e (带头结点)
51 {
52 if(i < 1) //只能在头结点之后插入,头结点是第0个,之后是第1个
53 {
54 List_HeadInsert(L); //头插法
55 }
56
57 LNode *p; //LNode * 强调这是一个结点,声明一个结点,表示指针p指向当前找到的结点
58 p = L; //L是指向头结点的头指针,再把刚开始的指针p指向L,表示目前的指针p指向头结点
59 int j = 0;//记录当前p指向的是第几个结点,从头结点0开始
60 while(p!= NULL && j < i - 1) //循环找到第 i-1 个结点,j = i-1,不进入循环,内存满了,不进入循环
61 {
62 p = p->next; //p指向下一个结点
63 j++;
64 }
65 if(p==NULL) //i值不合法,如果有4个结点,那i不能等于6,因为 p = p->next,在第5个位置之后满了,p指向NULL,下一步p->next出错了,根本找不到表的某个位置
66 return false;
67 LNode *s = (LNode *)malloc(sizeof(LNode));//创建一个节点,这个节点的数据域就是e
68 s->data = e;
69 s->next = p->next; //自己画图理解,一开始p后的节点不是s,这里让p的下一个节点变成了在s的下一个节点
70 p->next = s; //将结点s连到p之后
71 return true; //插入成功
72 }
73 void ShowList(LinkList L) //显示
74 {
75 if(L->next == NULL)
76 printf("这是一个空表\n");
77 while(L != NULL)
78 {
79 L = L->next;
80 printf("%d ",L->data);
81 }
82
83 }
84 bool DeleteList(LinkList &L, int i)//删除表L中第 i 个位置的元素,并用e返回删除元素的值。
85 {
86 if(i < 1)
87 return false;
88 LNode *p;
89 p = L;
90 int j = 0;
91 while(p != NULL && j < i - 1) //循环找第 i-1 个节点
92 {
93 p = p->next;
94 j++;
95 }
96 if(p == NULL) //i值不合法,导致第 i-1 个节点根本在表中找不到
97 return false;
98 if(p->next == NULL) //第 i-1 个节点能找到,但是刚好第 i-1 个节点之后已无其他节点(第i个结点和第i+1个节点没有了),那就没有办法把第 i-1 个节点的指向下一个节点的指针指向第 i+1 个节点
99 return false;
100 LNode *q = p->next; //p是第 i-1 个节点,p->next是之后的节点,也是第 i 个节点,令q指向被删除节点
101 p->next = q->next; //将*q 节点从链中断开,重新更改指针p的指向,指向第 i + 1个节点
102 free(q); //释放节s点的存储空间
103 return true;
104 }
105 int GetList(LinkList &L, int i)//按位查找,返回第 i 个元素(带头节点)
106 {
107 if(i < 0)//有头节点,头节点是第0个节点,所以查找元素i不能小于0
108 return -1;
109 LNode *p;
110 int j = 0;
111 p = L;
112 while(p != NULL && j < i) //找的是第i个节点,插入那里找的是第i-1 个节点
113 { //如果i大于表的长度,那循环找到的p会指向NULL,不会进入循环体,最后返回NULL
114 p = p->next;
115 j++;
116 }
117 return p->data;
118 } //平均时间复杂度为O(n)
119 int UpdateList(LinkList &L, int i, int num)
120 {
121 if(i < 0)//有头节点,头节点是第0个节点,所以查找元素i不能小于0
122 return 0;
123 LNode *p;
124 int j = 0;
125 p = L;
126 while(p != NULL && j < i) //找的是第i个节点,插入那里找的是第i-1 个节点
127 { //如果i大于表的长度,那循环找到的p会指向NULL,不会进入循环体,最后返回NULL
128 p = p->next;
129 j++;
130 }
131 p->data = num;
132 return p->data;
133 }
134 void Destroy(LinkList &L) //销毁单链表
135 {
136 LNode *p;
137 while(L != NULL)
138 {
139 p = L;
140 L = L->next;
141 free(p);
142 }
143 }
144 void ShowMenu()
145 {
146 printf("************************\n");
147 printf("***** 1,添加数据 *****\n");
148 printf("***** 2,删除数据 *****\n");
149 printf("***** 3,查找数据 *****\n");
150 printf("***** 4,修改数据 *****\n");
151 printf("***** 5,显示数据 *****\n");
152 printf("***** 6,头插法 *****\n");
153 printf("***** 7,尾插法 *****\n");
154 printf("***** 0,销毁并退出 ***\n");
155 }
156 int main()
157 {
158 LinkList L;//声明一个单链表
159 InitList(L);//初始化函数调用
160
161 int select = 0; //创建选择输入的变量
162 while (true)
163 {
164 //菜单调用
165 ShowMenu();
166 printf("请输入你的选择\n");
167 scanf("%d", &select);
168 switch (select)
169 {
170 case 1: //1,添加数据
171 InsertList(L,1,1);
172 InsertList(L,2,2);
173 InsertList(L,3,3);
174 InsertList(L,4,4);
175 InsertList(L,5,5);
176 printf("数据添加成功!\n");
177 getchar();
178 break;
179 case 2: //2,删除数据
180 DeleteList(L,1);
181 getchar();
182 break;
183 case 3: //3,查找数据
184 printf("查找的元素是:%d\n",GetList(L,1));
185 getchar();
186 break;
187 case 4: //4,修改数据
188 UpdateList(L,1,0);
189 printf("修改成功!\n");
190 getchar();
191 break;
192 case 5: //4,显示数据
193 printf("单链表的数据有:");
194 ShowList(L);
195 getchar();
196 break;
197 case 6: //头插法
198 List_HeadInsert(L);
199 getchar();
200 break;
201 case 7: //尾插法
202 List_TailInsert(L);
203 getchar();
204 break;
205 case 0: //0,退出
206 Destroy(L);
207 printf("单链表已销毁!");
208 printf("欢迎下次使用");
209 return 0;
210 break;
211
212 default:
213 break;
214 }
215 }
216 return 0;
217 }

206.反转链表

题目链接/文章讲解/视频讲解:https://programmercarl.com/0206.%E7%BF%BB%E8%BD%AC%E9%93%BE%E8%A1%A8.html

    卡哥题目建议:建议先看我的视频讲解,视频讲解中对 反转链表需要注意的点讲的很清晰了,看完之后大家的疑惑基本都解决了。
     做题思路:

链表的反转就是链表的逆置,从上个题就能看出,头插法是链表的逆置。

代码见上个题的。

代码随想录算法训练营第三天| LeetCode 203.移除链表元素(同时也对整个单链表进行增删改查操作) 707.设计链表 206.反转链表的更多相关文章

  1. java+jsp+sqlserver实现简单的增删改查操作 连接数据库代码

    1,网站系统开发需要掌握的技术 (1)网页设计语言,html语言css语言等 (2)Java语言 (3)数据库 (4)等 2,源程序代码 (1) 连接数据库代码 package com.jaovo.m ...

  2. 代码随想录算法训练营day01 | leetcode 704/27

    前言   考研结束半个月了,自己也简单休整了一波,估了一下分,应该能进复试,但还是感觉不够托底.不管怎样,要把代码能力和八股捡起来了,正好看到卡哥有这个算法训练营,遂果断参加,为机试和日后求职打下一个 ...

  3. 代码随想录算法训练营day12 | leetcode 239. 滑动窗口最大值 347.前 K 个高频元素

    基础知识 ArrayDeque deque = new ArrayDeque(); /* offerFirst(E e) 在数组前面添加元素,并返回是否添加成功 offerLast(E e) 在数组后 ...

  4. 代码随想录算法训练营day06 | leetcode 242、349 、202、1

    基础知识 哈希 常见的结构(不要忘记数组) 数组 set (集合) map(映射) 注意 哈希冲突 哈希函数 LeetCode 242 分析1.0 HashMap<Character, Inte ...

  5. 代码随想录算法训练营day03 | LeetCode 203/707/206

    基础知识 数据结构初始化 // 链表节点定义 public class ListNode { // 结点的值 int val; // 下一个结点 ListNode next; // 节点的构造函数(无 ...

  6. 代码随想录算法训练营day14 | leetcode 层序遍历 226.翻转二叉树 101.对称二叉树 2

    层序遍历 /** * 二叉树的层序遍历 */ class QueueTraverse { /** * 存放一层一层的数据 */ public List<List<Integer>&g ...

  7. 代码随想录算法训练营day07 | leetcode 454.四数相加II 383. 赎金信 15. 三数之和 18. 四数之和

    LeetCode 454.四数相加II 分析1.0 这个最直接暴力法,不过过于暴力了,害怕.jpg 失误 读题理解失误:题目要求的是四元组的个数,读完题到我这里成了输出四元组,悲哉 分析2.0 记录有 ...

  8. 代码随想录算法训练营day22 | leetcode 235. 二叉搜索树的最近公共祖先 ● 701.二叉搜索树中的插入操作 ● 450.删除二叉搜索树中的节点

    LeetCode 235. 二叉搜索树的最近公共祖先 分析1.0  二叉搜索树根节点元素值大小介于子树之间,所以只要找到第一个介于他俩之间的节点就行 class Solution { public T ...

  9. 代码随想录算法训练营day02 | leetcode 977/209/59

    leetcode 977   分析1.0:   要求对平方后的int排序,而给定数组中元素可正可负,一开始有思维误区,觉得最小值一定在0左右徘徊,但数据可能并不包含0:遂继续思考,发现元素分布有三种情 ...

  10. 代码随想录算法训练营day17 | leetcode ● 110.平衡二叉树 ● 257. 二叉树的所有路径 ● 404.左叶子之和

    LeetCode 110.平衡二叉树 分析1.0 求左子树高度和右子树高度,若高度差>1,则返回false,所以我递归了两遍 class Solution { public boolean is ...

随机推荐

  1. RTSP Server(LIVE555)源码分析(四)-SETUP信令

    主要分析RTSPServer::RTSPClientSession针对客户端SETUP事件处理 一. SETUP信令,handleCmd_SETUP源码解析 1)步骤1.03,parseTranspo ...

  2. 笔记:C++学习之旅---面向对象程序设计2

    笔记:C++学习之旅---面向对象程序设计2 面向对象程序设计基于三个基本概念:数据抽象.继承和动态绑定. 继承和动态绑定对程序的编写有两方面的影响:一是我们可以更容易的定义与其他类相似但不完全相同的 ...

  3. Prism Sample 15-FilteringEvents

    例14演示了怎样事件聚合器怎样发布与接收信息. 例15增加了一个事件的过滤功能,即设定一个条件,符合的才接收. _ea.GetEvent<MessageSentEvent>().Subsc ...

  4. pytest测试实战和练习

    开头 经过前面几章的学习,这时候要来个测试实战会比较好巩固一下学过的知识 任务要求 1.实现计算器(加法,除法)的测试用例 2.使用数据驱动完成测试用例的自动生成 3.在调用测试方法之前打印[开始计算 ...

  5. 2021-08-01:如果只给定一个二叉树前序遍历数组pre和中序遍历数组in,能否不重建树,而直接生成这个二叉树的后序数组并返回。已知二叉树中没有重复值。

    2021-08-01:如果只给定一个二叉树前序遍历数组pre和中序遍历数组in,能否不重建树,而直接生成这个二叉树的后序数组并返回.已知二叉树中没有重复值. 福大大 答案2021-08-01: 先序遍 ...

  6. Django4全栈进阶之路9 STATIC静态文件路径设置、MEDIA媒体文件路径设置

    在 Django 4 中,可以在 settings.py 文件中设置 STATICFILES_DIRS 来指定应用程序静态文件所在的文件夹路径,设置 STATIC_ROOT 来指定收集所有应用程序静态 ...

  7. 【LeetCode双向链表】LRU详解,双向链表实战

    LRU缓存 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构. 实现 LRUCache 类: LRUCache(int capacity) 以 正整数 作为容量 capacity ...

  8. .Net NPOI Excel 导出

    NPOI 导出 Excel 最终效果图 环境:Revit,WPF,NPOI 2.5.6,.Net Framework 4.7.2 一.引用 NPOI 右击项目引用,选择 "管理NuGet程序 ...

  9. JS和Document

    对象1.new var obj = new Object(); 2.函数声明对象 function Human () {}: 3.var obj = {}; 大括号 就是对象var obj = {}; ...

  10. 今天在内部 Galaxy 分析平台操作探针引物设计小工具程序,调用 Ensembl API 获取相关序列和信息时,发现官网 MySQL server 异常,报告问题后当天晚上就收到了回复,并且修......

    本文分享自微信公众号 - 生信科技爱好者(bioitee).如有侵权,请联系 support@oschina.cn 删除.本文参与"OSC源创计划",欢迎正在阅读的你也加入,一起分 ...