「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战」
题目_旋转链表
给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k **个位置。
示例 1:
暴力解法
拿到这题,第一反应就是,找到链表倒数第二个节点,然后将倒数第二个节点的指针指向null,将最后一个节点的指针指向头节点,循环k次即可。
再考虑边界情况,空链表,或者链表只有一个节点,则直接返回头节点。
三下五除二,解法写出来了,但是,时间超限制了,哈哈。
没事,分析发现,假设链表长度是4
旋转次数为4,那么实际旋转0次
旋转次数为5,那么实际旋转1次
旋转次数为k, 那么实际旋转次数为(k/链表长度)得到的余数,即k%length
暴力解法代码
/**
* @param {ListNode} head
* @param {number} k
* @return {ListNode}
*/
var rotateRight = function(head, k) {
if(!head || !head.next || k == 0){
return head
}
let length = getListLength(head)
let realCount = k%length
let headNode = head
for(let i=0;i<realCount;i++){
let lastSecondNode = getLastSecondNode(headNode)
let lastNode = lastSecondNode.next
lastSecondNode.next = null
lastNode.next = headNode
headNode = lastNode
}
return headNode
};
function getListLength(head){
let cur = head
let length = 0
while(cur){
cur = cur.next
length++
}
return length
}
function getLastSecondNode(head){
let cur = head
while(cur && cur.next && cur.next.next){
cur = cur.next
}
return cur
}
链表成环再截断解法
假设链表长度是4,循环5次,其实可以理解为,头节点向右移动3次
那么~~
假设链表长度是L,循环K次,其实可以理解为,头节点向右移动L - K/L
那么我们可以
1.拿到链表长度length
2.将链表成环
3.计算移动步数move
4.从头节点开始向右移动move步,找到真正的头节点
5.截断链表,返回真正的头节点
链表成环解法代码如下
/**
* @param {ListNode} head
* @param {number} k
* @return {ListNode}
*/
var rotateRight = function(head, k) {
// 链表节点为0或1 || 循环次数为0
if(!head || !head.next || k == 0){
return head
}
// 获取链表长度
let cur = head
let length = 1
while(cur.next){
cur = cur.next
length++
}
cur.next = head //链表成环
let move = length - k%length //计算移动步数
let realHead = head //realHead用于存放真正的头节点,return的就是这个realhead
let lastHead //lastHead用于存放真正的尾节点,用来截断链表
while(move){
lastHead = realHead
realHead = realHead.next
move--
}
lastHead.next = null
return realHead
};