今天又刷了一道链表的题,初次接触链表的题目,感觉还是有一定难度的,下面和大家来分享一下经验吧!
题目如下:
Reverse a linked list from position m to n. Do it in one-pass.
Note: 1 ≤ m ≤ n ≤ length of list.
Example:
Input: 1->2->3->4->5->NULL, m = 2, n = 4
Output: 1->4->3->2->5->NULL
题意分析:
给定一个单链表,请将其按给定的区间[m,n]进行反转。
注:1 ≤ m ≤ n ≤ 列表的长度。
解答如下:
方法一(反转[m,n]节点再串起来)
先创建一个新节点,并指向待反转链表的head(为了避免因后续指针的移动而导致没有指针指向前面的节点),然后创建两个指针(pre,curNode),用for循环(i < m)跳过无须反转的节点,之后再创建两个指针(p1,p2)配合pre、curNode进行反转对应节点(pre用于指向断开处的前一个节点(保护现场作用),curNode、p1、p2用于进行反转,其中p1处于反转的核心地位),通过for循环(m ≤ i < n:若要反转3个节点其实只需循环2次)便可完成相应节点的反转。最后,该起到“保险现场”作用的节点pre登场了,通过pre ->next ->next = p1;pre ->next = curNode;将子链表串成最终待求的链表,并返回待求链表的头指针,即dummpy -> next。
代码①:
class Solution{
public:
ListNode* reverseBetween( ListNode* head, int m, int n){
ListNode* dummpy = new ListNode(-1); \\新建一个节点,-1是该新节点的value
dummpy ->next = head;
ListNode* pre = dummpy;
ListNode* curNode = head;
\\过滤无须反转节点
for (int i = 1; i < m; i++) {
pre = curNode;
curNode = curNode ->next;
}
ListNode* p1;
ListNode* p2;
if (curNode)
p1 = curNode ->next;
if (p1)
p2 = p1 ->next;
\\反转需要反转节点
for (int i = m; i < n; i++)
{p1 ->next = curNode;
curNode = p1;
p1 = p2;
if (p2)
p2 = p2 ->next;}
pre ->next ->next = p1; \\恢复现场
pre ->next = curNode; \\恢复现场
return dummpy -> next; \\返回所求链表头指针
}
};
代码②(①的优化):
class Solution{
public:
ListNode* reverseBetween( ListNode* head, int m, int n){
ListNode* dummpy = new ListNode(-1);
dummpy ->next = head;
ListNode* pre = dummpy;
for (int i = 1; i < m; i++) {
pre = pre ->next;
}
ListNode* p1;
ListNode* p2;
ListNode* curNode = pre ->next;
if (curNode)
p1 = curNode ->next;
if (p1)
p2 = p1 ->next;
for (int i = m; i < n; i++)
{p1 ->next = curNode;
curNode = p1;
p1 = p2;
if (p2)
p2 = p2 ->next;}
pre ->next ->next = p1;
pre ->next = curNode;
return dummpy -> next;
}
};
提交后的结果如下:
方法二(将[m,n]中的节点依次往前插入)
该方法主要有两点:
①:通过for循环过滤无须反转的节点
②:创建临时的tmp指针指向需要反转的节点,通过for循环将需要反转的节点往前插入。该方法中tmp指针处于核心地位。
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
ListNode* dummy = new ListNode(-1), *pre = dummy;
dummy -> next = head;
for (int i = 1; i < m ; i++) pre = pre -> next; //过滤无须反转的节点
ListNode* cur = pre -> next;
for (int i = m; i < n; i++) { //将需要反转的节点往前插入
ListNode* tmp = cur -> next; //创建临时的tmp指针指向需要反转的节点
cur -> next = tmp -> next;
tmp -> next = pre -> next;
pre -> next = tmp;
}
return dummy -> next;
}
};
提交后的结果如下:
日积月累,与君共进,增增小结,未完待续。