题目
给定一个链表,旋转链表,将链表每个节点向右移动 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
大于链表长度length
,则只需要重复上述步骤k % length
次。
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @param {number} k
* @return {ListNode}
*/
var rotateRight = function(head, k) {
// 如果是 空链表或者只有一个元素的链表,则返回该链表
if(!head || !head.next) return head
// 设置指针,指向头部
var cur = head
// 从头部开始循环,获取链表长度。由于头部也是一个节点,所以 length 初始值为1
var length = 1;
while(cur.next) {
cur = cur.next
length++
}
// 获取实际要重复的次数
var num = k % length
// 用一个新指针指向头部
var node = head
// 拿掉最后一个, 把它放在头部, 重复num次
while(num > 0){
var last = node
// 拿到倒数第二个
while (last.next && last.next.next) {
last = last.next
}
// 获取最后一项的值
var val = last.next.val
// 去掉最后一项
last.next = null
// 把最后一项的值 往头部添加
let vhead = new ListNode(val)
vhead.next = node
node = vhead
num--
}
return node
};
方法二
对于方法一来说,由于是双层循环,时间复杂度比较高。我们可以做一些优化。
对于链表来说,最终的长度是不变的,其实我们无需每次循环都找到倒数第二个节点作为尾部节点,只需要将链表首尾相连,按照既定的循环次数进行循环,最终断开即可。
实现方法也很直接。
- 将链表首尾相连,计算出链表的长度
length
和步数k % length
。 - 找到新的链表头,由于是从链表尾部走
k % length
步,就相当于从链表头走lengt - k % length
,链表尾部是链表头部前一个,即length - k % length - 1
个节点。 - 断开环,并返回新的链表头。
此处,我们同样可以使用双指针共同前进完成。
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @param {number} k
* @return {ListNode}
*/
var rotateRight = function(head, k) {
// 如果是 空链表或者只有一个元素的链表,则返回该链表
if(!head || !head.next) return head
var cur = head
// 从头部开始循环,获取链表长度。由于头部也是一个节点,所以 length 初始值为1
var length = 1;
while(cur.next) {
cur = cur.next
length++
}
// 获取实际要重复的次数
var num = k % length
// 链表闭环
cur.next = head
var new_list = head
// 找到新的尾部 new_tail : 走length - k % length - 1 步
// 找到新的头部 new_head : 走length - k % length 步
for(var i = 0;i < length - num - 1 ; i++){
new_tail = new_tail.next
}
var new_head = new_tail.next
new_tail.next = null
return new_head
};