版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010365335/article/details/86750711
目录
234.回文链表
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2 输出: false
示例 2:
输入: 1->2->2->1 输出: true
解析:回文即正反序都一样,所以只要找出中间节点,然后翻转后面部分的链表,再一一进行比较
(找到中间节点,为LeetCode876.链表的中间节点题一样)
解法:
1.快慢指针找出中间节点,快指针每次走两个,慢指针走一格
2.翻转后边部分
3.一一比较,得出结果
class Solution {
function isPalindrome($head) {
$dummyHead = new ListNode(null);
$dummyHead->next = $head;
//快满指针取中间位置
$centerNode = $doubleNode = $dummyHead;
while($doubleNode->next){
$centerNode = $centerNode->next;
$doubleNode = $doubleNode->next->next;
}
//翻转后边部分
$preNode = null; //前节点
$curNode = $centerNode->next; //后部分的第一个节点
while ($curNode) {
$nextNode = $curNode->next;
$curNode->next = $preNode;
$preNode = $curNode;
$curNode = $nextNode;
}
//一一比较
$curNode = $dummyHead->next;
//遍历结束,$preNode指向反转后,后面部分的第一个节点
while ($curNode && $preNode) {
if($curNode->val != $preNode->val){
return false;
}
$curNode = $curNode->next;
$preNode = $preNode->next;
}
return true;
}
}
143.重排链表
给定一个单链表 L:L0→L1→…→Ln-1→Ln ,
将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1: 给定链表 1->2->3->4, 重新排列为 1->4->2->3.
示例 2: 给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.
解析:解法与234.回文链表类似,区别:这道题不是要比较,而是进行重新连接
解法:
1.快慢指针找出中间节点,快指针每次走两个,慢指针走一格
2.翻转后边部分,区分出两条单链表
3.一一链接,得出结果
class Solution {
function reorderList($head) {
$dummyHead = new ListNode(null);
$dummyHead->next = $head;
//快慢指针取中间位置
$centerNode = $doubleNode = $dummyHead;
while($doubleNode->next){
$centerNode = $centerNode->next;
$doubleNode = $doubleNode->next->next;
}
//翻转后边部分
$preNode = null;
$curNode = $centerNode->next;
while ($curNode) {
$nextNode = $curNode->next;
$curNode->next = $preNode;
$preNode = $curNode;
$curNode = $nextNode;
}
/**
* 将前部分的链表封尾,就完成构建两条链表
* head -> 1 -> 2 -> 3 -> end
* head-> 5 -> 4 -> end
*/
$centerNode->next = null;
//两两合并,初始化两个链表的头节点
$curNode = $dummyHead->next;
$revNode = $preNode;
while ($revNode) {
//存下一节点
$curNextNode = $curNode->next;
$revNextNode = $revNode->next;
//交换节点
$curNode->next = $revNode;
$revNode->next = $curNextNode;
//重新定义节点
$curNode = $curNextNode;
$revNode = $revNextNode;
}
return $dummyHead->next;
}
}
61.旋转链表
给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。
示例 1:
输入: 1->2->3->4->5->NULL, k = 2 输出: 4->5->1->2->3->NULL 解释: 向右旋转 1 步: 5->1->2->3->4->NULL 向右旋转 2 步: 4->5->1->2->3->NULL
示例 2:
输入: 0->1->2->NULL, k = 4 输出:2->0->1->NULL 解释: 向右旋转 1 步: 2->0->1->NULL 向右旋转 2 步: 1->2->0->NULL 向右旋转 3 步: 0->1->2->NULL 向右旋转 4 步: 2->0->1->NULL
解析:从示例不难看出,该旋转可以看成是头尾节点链接,形成循环链表,再去找到倒数第K个节点,断开则得到答案
解法:
1.头尾链接并计算出链表长度$len
2.计算移动长度,$len = $len - ($k%$len) ,因为旋转次数=链表长度时,链表不变
3.旋转链表
class Solution {
function rotateRight($head, $k) {
$dummyHead = new ListNode(null);
$dummyHead->next = $head;
//1.头尾链接并计算出链表长度
$curNode = $head;
$len = 1;
while ($curNode->next) { //计算链表长度
$curNode = $curNode->next;
$len++;
}
$curNode->next = $head; //循环后curNode指向尾节点,进行头尾链接
//2.计算移动长度
$len = $len - ($k%$len);
//3.旋转链表
$tailNode = $curNode; //指向尾节点,也是旋转链表完成后的最后一个节点
$curNode = $head; //指向当前的头节点,也是旋转链表完成后的第一个节点
for($i = 0;$i<$len;++$i){
$curNode = $curNode->next;
$tailNode = $tailNode->next;
}
$tailNode->next = null; //对尾指针进行封尾
return $curNode; //返回头节点进行遍历即可
}
}