【PHP解法==LeetCode链表类型(经典问题,反转链表)】206.反转链表 && 92.反转链表 II && 24. 两两交换链表中的节点 && 25. k个一组翻转链表(Hard)

目录

206.反转链表 

92.反转链表 II

24. 两两交换链表中的节点

25. k个一组翻转链表(Hard)


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)

给出一个链表,每 个节点一组进行翻转,并返回翻转后的链表。

是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 的整数倍,那么将最后剩余节点保持原有顺序。

示例 :

给定这个链表:1->2->3->4->5

当 = 2 时,应当返回: 2->1->4->3->5

当 = 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;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值