目录
206.反转链表
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL
$preNode : 指向前一节点 $curNode : 指向当前节点 $nextNode : 保存下一节点
1.初始化时,$preNode指向空指针,$curNode指向$head,$nextNode保存下一节点(要先保存下一节点,因为当下一步操作时,$curNode->next已经改变,就会找不到真正的下一节点)
2.改变当前指针$curNode的下一节点,指向前一节点$preNode
3.第2步循环,直到链表遍历完毕
class Solution {
function reverseList($head) {
$preNode = null; //前一节点
$curNode = $head;//当前节点
while ($curNode) {
$next = $curNode->next;//保存下一节点
$curNode->next = $preNode;
$preNode = $curNode;
$curNode = $next;
}
return $preNode;
}
}
92.反转链表 II
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明: 1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4 输出: 1->4->3->2->5->NULL
解析:即是区间内的翻转链表,找到开始翻转区间的前一节点,进行同206题的翻转过程即可
说明:因可能操作到头节点,为了避免对头节点特殊处理,增加冗余代码,可以增加一个虚拟头节点$dummyHead
class Solution {
function reverseBetween($head, $m, $n) {
if($m == $n) return $head;
//建立一个虚拟头节点
$dummyHead = new ListNode(null);
$dummyHead->next = $head;
$curNode = $dummyHead;
//找到前一节点
for($i = 0;$i<$m-1;++$i){
$curNode = $curNode->next;
}
$revesePreNode = $curNode; //不需要翻转的前面部分的最后一个节点
$revesedTailNode = $curNode->next;//开始翻转的第一个节点=>翻转后的最后一个节点
//开始交换
$preNode = null;
$curNode = $curNode->next;
//交换过程
for($i = $i+1;$i<=$n;++$i){
$nextNode = $curNode->next;
$curNode->next = $preNode;
$preNode = $curNode;
$curNode = $nextNode;
}
$revesePreNode->next = $preNode;
$revesedTailNode->next = $curNode;
return $dummyHead->next;
}
}
24. 两两交换链表中的节点
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
示例:
给定 1->2->3->4, 你应该返回 2->1->4->3
说明:
- 你的算法只能使用常数的额外空间。
- 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
解法:1.初始化,构建一个虚拟头节点,$node1指向第一个要交换的节点,$node2指向第二个要交换的节点,$curNode要进行交换部分的前一节点
2.改变$node1的下一节点为$node2的下一节点,$node2指向第一个要交换的节点$node1,$curNode的下一节点指向$node2,因为$node2调换到了前面
3.$curNode继续指向下一次交换的前一节点,即$node1位置,根据$curNode继续循环,直到链表遍历完毕
class Solution {
function swapPairs($head) {
$dummyHead = new ListNode(null);
$dummyHead->next = $head;
$curNode = $dummyHead;
while ($curNode->next && $curNode->next->next) {
$node1 = $curNode->next; //第 1 个要交换的节点
$node2 = $node1->next; //第 2 个要交换的节点
$node1->next = $node2->next;//1.先指向下一节点,否则后面会改变
$node2->next = $node1; //2.node2指向node1
$curNode->next = $node2; //3.前一节点,指向node2
$curNode = $node1; //4.curNode指向下一次交换的前一节点
}
return $dummyHead->next;
}
}
25. k个一组翻转链表(Hard)
给出一个链表,每 k 个节点一组进行翻转,并返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么将最后剩余节点保持原有顺序。
示例 :
给定这个链表:
1->2->3->4->5
当 k = 2 时,应当返回:
2->1->4->3->5
当 k = 3 时,应当返回:
3->2->1->4->5
解析:当k=2时,题目要求同24题一致,该题是将24,92题结合起来
解法:1.检测是否满足翻转条件 2.保存所需指针 3.进行翻转
class Solution {
function reverseKGroup($head, $k) {
//链表
//建立一个虚拟头节点
$dummyHead = new ListNode(null);
$dummyHead->next = $head;
$curNode = $dummyHead;
while ($curNode->next) {
//检测是否满足翻转条件
$checkNode = $curNode->next;
for($i = 1;$i<$k;++$i){
if(is_null($checkNode->next)){
return $dummyHead->next;
}
$checkNode = $checkNode->next;
}
//保存所需节点
$revesedTailNode = $checkNode->next; //开始翻转的第一个节点=>翻转后的最后一个节点
$revesePreNode = $curNode; //不需要翻转的前面部分的最后一个节点
$reverseNode = $curNode = $curNode->next;//开始交换的第一个节点
$secondNode = $curNode->next; //开始交换的第二个节点
$nextNode = $secondNode->next; //保存下一节点
//交换过程
for($i = 1;$i<$k;++$i){
$secondNode->next = $curNode;
$curNode = $secondNode;
$secondNode = $nextNode;
$nextNode = $nextNode->next;
}
$revesePreNode->next = $curNode; //$curNode最终指向交换区间的最后一个节点=>捋顺后的第一个节点
$reverseNode->next = $revesedTailNode;
$curNode = $reverseNode;
}
return $dummyHead->next;
}
}