从尾到头打印链表 之 “C++代码+思路解析 ”(允许原地修改链表)
上一篇 从尾到头打印链表 (第一种情况 不允许原地打印链表)
希望我的文字始终给您带来画面感。
其实做算法题的过程也是在考验我们的大脑日常解决问题的能力,懂不懂得将生活中碰到的难题拆分,一一解决。
今日感悟:
//不要去刻意记忆代码句,先用起来,积累框架,慢慢拿出来用。
//不是所有的框架都是一样的,也要学会适应不同的变化。
题目开始咯!
题目描述:输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
//这里敲黑板,千万注意:我们做算法题 ,最基本的也是最关键的题目一定要 理解准确。这道题涉及到允不允许原地修改链表,所以分为以下两种情况。这里是第二种情况。
第二种情况:允许原地修改链表,那么只需要用三个指针来解决。
代码实现部分:
//5月9日
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre = nullptr;
ListNode* cur = head;
ListNode* next = nullptr;
while(cur)
{
next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
};
思路解析部分:
我不知道大家的写算法思路是思维习惯和先后顺序是怎样的,我会习惯将代码拆分成小的代码块进行 ,再进行逻辑组合安装。当然这里无法评判哪种一定是正确的,这里我想分享一下:我个人认为最快的写代码顺序。
第一步:我会先搞清楚题目 ,需要我给它一个什么,定下来整体的框架。
这道题的第二种情况是允许原地修改链表,那么只需要返回传进来的链表就OK了,只不过这个链表被操作了一番。
那第一步函数整体的框架就出来咯!
class Solution {
public:
ListNode* reverseList( ) {
.............................................
return 头指针;//链表被原地操作,此时的头指针已经不是head了
}
};
这里的第二步:我会把参数定下来,进到函数体首先就检查参数合不合法。
加入 if 语句检验参数 链表指针 head 是否为空。
class Solution {
public:
ListNode* reverseList( ListNode* head) {
if( !head )
{
return head;
}
.............................................
return 头指针;
}
};
第三步:给框架里面填上语句块。发挥( if,while,for…)语句的作用,语句其实就是思考逻辑的实现。
原地反转链表的逻辑就是把链表的数值比如-1-2-3-4-5-变成-5-4-3-2-1-。这里设置三个指针 ,前后中分别用cur,pre和next来表示。
1 填入 这块代码,使用while 语句做不断重复做两件事。
第1件事:使得当前结点的后继结点变成前驱结点,也就是2的后面不连3,要连1。用这句代码来实现这件事:cur->next = pre;
第2件事:不断推动三个指针向后走。用这三句代码来实现。
1next = cur->next; …(第一件事)…2 pre = cur; 3 cur = next;
大家都看出来了这三句是有顺序的。进入循环时一定要先把cur->next保存起来,使next先后移一步,不然下一步cur的后继结点的改变会让next指向乱掉。然后前指针和当前指针一起向后移动。
while ( cur )
{
next = cur->next;
cur->next = pre; //使当前结点的后继结点变成前驱结点。
pre = cur;
cur = next;
}
第四步:抠细节,这里给加上定义,附上初值。
1 给变量加上定义+赋值。
ListNode* pre = nullptr;
ListNode* cur = head;
ListNode* next = nullptr;
此题总结:
这道题目最大的难点就在于拆分语句的四句代码 ,怎样安排三指针的移动顺序,还有就是进入循环体就一定要先把当前结点的后继结点保存起来。