给定一个链表,旋转链表,将链表每个节点向右移动 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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/rotate-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
——————————————————————————————————————————————————————
思路:
本题可以通过多次遍历、额外数组存储空间等方法来实现。
这里分享一个空间复杂度为O(1),时间复杂度为O(n)的方法。(n为链表长度)。
惯例,我会先申请一个空节点resHead作为新链表的头节点,那么整个返回节点指向:resHead->next
首先一趟遍历,得到链表长度l,然后将原单链表改造成为循环链表,并记录下链表最后一个节点的位置为resEnd;
然后计算offset = k%l,把旋转的数值控制到n以内;
最后根据计算的offset,移动head和resEnd节点,移动步数为l-offset,注意这一步很关键,因为旋转可以看作是找头节点和尾节点,比如k=2,就是要找倒数第二个节点作为头节点,倒数第3个作为尾节点。通过计算后可以得到:head移动l-offset为新的头,resEnd为新的尾。
然后用resHead.Next = head 和 resEnd.Next = nil 切断循环链表,构造新链表。
go实现:
func rotateRight(head *ListNode, k int) *ListNode {
if head == nil {
return head
}
resHead := &ListNode{0,nil}
resEnd := resHead
l := 0
for p:=head;p!=nil;p=p.Next {
l++
if p.Next == nil {
p.Next = head
resEnd = p
break
}
}
offset := k%l
for i:=0;i<l-offset;i++ {
head = head.Next
resEnd = resEnd.Next
}
resHead.Next = head
resEnd.Next = nil
return resHead.Next
}
python实现:
class Solution:
def rotateRight(self, head: ListNode, k: int) -> ListNode:
resHead = ListNode(0)
resEnd = ListNode(0)
if head is None:
return head
p = head
l = 0
while p is not None:
l+=1
if p.next is None:
p.next = head
resEnd = p
break
p = p.next
offset = k%l
i = 0
while i<l-offset:
head = head.next
resEnd = resEnd.next
i+=1
resHead.next = head
resEnd.next = None
return resHead.next