剑指offer系列9:反转链表

两个思路:

1.将传来的链表结点一个一个反转,需要使用3个指针,分别指向前结点、当前结点、后结点。

2.从表头开始遍历,每遍历一个结点,将该结点存入一个新链表的头结点。

先说第一个,这个我做的时候有点绕,认真的把结点的指针图画出来理清楚了思路。注释把思路解释的很清楚了,代码如下:

 1 #include<iostream>
 2 using namespace std;
 3 struct ListNode {
 4 int val;
 5 struct ListNode *next;
 6 ListNode(){}//这样写就是加了一个默认的构造函数,无参数
 7 //val(x), next(NULL)
 8
 9 };
10 class Solution {
11 public:
12     ListNode* ReverseList(ListNode* pHead) {
13         if (pHead == NULL)
14             return NULL;
15         if (pHead->next == NULL)
16             return pHead;
17         ListNode*p1 = pHead;
18         ListNode*p2 = pHead;
19         ListNode*p3 = pHead;
20         p1 = pHead->next;
21         p2->next = NULL;
22         while (p1!= NULL)
23         {
24             p2 = p1->next;//用来暂存指向下一个结点的指针
25             p1->next = p3;
26             //p3 = p2->next;
27             p3 = p1; //始终让p3做前结点
28             p1 = p2; //始终让p1做当前结点
29         }
30         return p3; //一直是p1做当前结点,但是后面将p3指向p1,所以应该返回p3
31
32     }
33 };
34 int main()
35 {
36     Solution so;
37     struct ListNode list[4];//突然明白了,在这里定义的list是无参的,因此必须存在无参的构造函数,而之前我定义了一个有参的构造函数,所以系统不会给定义默认的无参构造函数
38                             //要定义无参的结构体变量,必须给它加上无参的构造函数
39     list[0].val = 1;
40     list[0].next = &list[1];
41     list[1].val = 2;
42     list[1].next = &list[2];
43     list[2].val = 3;
44     list[2].next = &list[3];
45     list[3].val = 4;
46     list[3].next = NULL;
47     ListNode *re = so.ReverseList(list);
48     while(re!=NULL)
49     {
50         cout << re->val << endl;
51         re= re->next;
52     }
53     return 0;
54 }

记得本科上c++课的时候,老师强调,new和delete一定要同时使用。所以在后来我用指针的时候总想着delete,包括定义指针变量也想delete。new是开辟一个空间出来,所以需要用delete释放这个空间。但是定义指针变量时,它只是一个变量,所有的变量都不需要释放,释放的是内存空间。

第二种方法,重新建立一个链表:

 1 class Solution {
 2 public:
 3     ListNode* ReverseList(ListNode* pHead) {
 4         if (pHead == NULL)
 5             return NULL;
 6         ListNode*p1 = NULL;
 7         ListNode*p2 = NULL;
 8         ListNode*p3 = NULL;
 9         while (pHead != NULL)//头插法插入
10         {
11             p2 = p1;
12             p1 = pHead;
13             p3 = pHead->next;
14             p1->next = p2;
15             pHead = p3;
16         }
17         return p1;
18
19     }
20 };

这是我看答案后的版本,其实跟我的思路差不多,我的想法是吧原来的结点的第一个结点取出来然后头插插入我的新链表中。而答案的想法是直接将原来链表的第一个结点指向创建的新链表,这样可以少建立一个变量。

代码如下:

 1 class Solution {
 2 public:
 3     ListNode* ReverseList(ListNode* pHead) {
 4         if (pHead == NULL)
 5             return NULL;
 6         ListNode*p = pHead;
 7         ListNode*Pnode = NULL;//创建新的链表结点
 8         ListNode*Pnext = NULL;//用来保存原来链表的下一个结点,以防丢失
 9         Pnode = p;            //首先给第一个结点建立
10         Pnext = p->next;
11         Pnode->next = NULL;
12         p = Pnext;
13         while (p!= NULL)
14         {
15             Pnext = p->next;
16             p->next = Pnode;
17             Pnode = p;
18             p = Pnext;
19         }
20         return Pnode;
21
22     }
23 };

其实没必要把第一个结点单独拿出来,直接放在while里也可以,于是得到了最精简的版本:

 1 class Solution {
 2 public:
 3     ListNode* ReverseList(ListNode* pHead) {
 4         if (pHead == NULL)
 5             return NULL;
 6         ListNode*p = pHead;
 7         ListNode*Pnode = NULL;//创建新的链表结点
 8         ListNode*Pnext = NULL;//用来保存原来链表的下一个结点,以防丢失
 9         while (p!= NULL)//头插法插入
10         {
11             Pnext = p->next;
12             p->next = Pnode;
13             Pnode = p;
14             p = Pnext;
15         }
16         return Pnode;
17
18     }
19 };

这个题还是有代表意义的,推荐使用第二种,更简单一些,思路也更清晰。只需要建立两个指针分别指向新的链表和原来链表的下一个结点。

原文地址:https://www.cnblogs.com/neverland0718/p/10987769.html

时间: 2024-08-29 09:53:44

剑指offer系列9:反转链表的相关文章

剑指offer系列13---反转链表并输出头结点

[题目]输入一个链表,反转链表后,输出链表的所有元素. [思路]将当前指针指向前者即为反转,反转是同时反转指针和赋值操作.即将指针指向前者并给前者赋值.反转后的头结点就是原链表的尾 结点.代码如下: 1 package com.exe3.offer; 2 /** 3 * 13[题目]输入一个链表,反转链表后,输出链表的所有元素. 4 * @author WGS 5 * 6 */ 7 public class ReverseLinkList { 8 public static class Link

剑指offer六:反转链表

输入一个链表,反转链表后,输出链表的所有元素 public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } public class Solution { public ListNode ReverseList(ListNode head) { ListNode pre = null; ListNode next = null; while(head != null){

剑指offer系列62---两个链表的公共结点

[题目]输入两个链表,找出它们的第一个公共结点. * [思路]1 获取两链表的长度: * 2 让长的链表先走n步后此时走到短链表起始位置: * 3 两链表同时遍历,直至相同,这时返回第一个公共结点. 1 package com.exe11.offer; 2 3 /** 4 * [题目]输入两个链表,找出它们的第一个公共结点. 5 * [思路]1 获取两链表的长度: 6 * 2 让长的链表先走n步后此时走到短链表起始位置: 7 * 3 两链表同时遍历,直至相同,这时返回第一个公共结点. 8 * @

剑指offer系列——25.复杂链表的复制

Q:输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head.(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空) T: A:代码: RandomListNode* Clone(RandomListNode* pHead) { if(!pHead) return NULL; RandomListNode *cur = pHead; while(cur){ RandomListNode *nod

剑指offer python版 反转链表

class ListNode(object): def __init__(self,x): self.val=x self.next=None class Link(object): def __init__(self,values=None): self.nodes=self.set_link(values) if values else None def get_link(self): return self.nodes def set_link(self,values): if not v

剑指Offer系列之题11~题15

目录 11.矩形覆盖 12.二进制中1的个数 13. 数值的整数次方 14.调整数组顺序使奇数位于偶数前面 15.链表中倒数第k个结点 11.矩形覆盖 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 比如n=3时,2*3的矩形块有3种覆盖方法: 斐波那契数列的应用 第一次竖着放一块类比为走一步,第一次横着放两块类比为走两步 代码与上面的斐波那契数列类题目类似,此处不再赘述:剑指Offer系列之题6~题10. 12.

剑指offer (37) 两个链表的第一个公共结点

题目:输入两个链表,找出它们的第一个公共结点 如果两个链表有公共结点,那么公共结点一定出现在两个链表的尾部 如果两链表长度不相等,那么达到公共结点的步数就不一致,如何确保 两个链表从头开始遍历,同步达到公共结点? 这是关键所在 如果两链表长度相同,那么就可以同步达到了? 由此,我们就需要 让两个链表长度"相等" 我们假设 两链表长度分别为m和n,且m > n, 那么我们可以在较长链表中 先走 m - n 步,然后 两个链表游标同步走,如果有公共结点,那么就一定同时达到 ListN

剑指OFFER之合并有序链表(九度OJ1519)

题目描述: 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则.(hint: 请务必使用链表.) 输入: 输入可能包含多个测试样例,输入以EOF结束.对于每个测试案例,输入的第一行为两个整数n和m(0<=n<=1000, 0<=m<=1000):n代表将要输入的第一个链表的元素的个数,m代表将要输入的第二个链表的元素的个数.下面一行包括n个数t(1<=t<=1000000):代表链表一中的元素.接下来一行包含m个元素,s(1<

【剑指offer】两个链表的第一个公共结点

转载请注明出处:http://blog.csdn.net/ns_code/article/details/26097395 简单题,剑指offer上的第37题,九度OJ上AC. 题目描述: 输入两个链表,找出它们的第一个公共结点. 输入: 输入可能包含多个测试样例.对于每个测试案例,输入的第一行为两个整数m和n(1<=m,n<=1000):代表将要输入的两个链表的元素的个数.接下来的两行,第一行为第一个链表的所有元素,中间用空格隔开.第二行为第二个链表的所有元素,中间用空格隔开. 输出: 对应

剑指offer系列10:合并两个排序的链表

我拿到这个题的时候举的例子是链表1:1.3.5.7和链表2:2.4.6.8.我的思路是以:1为基础,将表2的每个结点插入表1.也就是说我一次性是要给新建立的链表中加入两个元素,分别是两个原始链表的头结点.这个思路我做了半天头脑一片混乱,中间指针实在不知道怎么弄了.于是我去睡了一觉,哈哈,我大概是这个世界上最会逃避的人了…… 看了答案使用了递归的方法,其实我做的时候我有想到要用递归,但是没用的原因是我一般写代码不喜欢用递归,原因有两个,一个是递归容易死循环,一个是递归的复杂度太高.但这道题真的太适