rotate-list(循环移动链表)

博客围绕链表循环移动问题展开,题目要求将链表向右循环移动 k 个位置(k 为非负)。文中给出三种解决方案,分别是截断重组思路、将链表首尾相接成循环链表以及常规循环思路。

题目描述

Given a list, rotate the list to the right by k places, where k is non-negative.

For example:
Given1->2->3->4->5->NULLand k =2,
return4->5->1->2->3->NULL.

Solution 1(截断重组思路)

class Solution {
public:
    ListNode *rotateRight(ListNode *head, int k) {
        if(head==NULL||head->next==NULL) return head;
        ListNode *pre=new ListNode(-1);
        pre->next=head;
        int ListLen=0,pos;
        ListNode *p=head,*q,*r;
        while(p!=NULL)
        {
            ++ListLen;
            p=p->next;
        }
        pos=ListLen-k%ListLen;
        if(pos==ListLen) return head;
        p=head;
        for(int i=0;i<pos-1;++i)
            p=p->next;
        q=pre->next;
        pre->next=p->next;
        r=p;
        while(r->next!=NULL)
            r=r->next;
        r->next=q;
        p->next=NULL;
        return pre->next;
    }
};

Solution 2 (将链表首尾相接成一个循环链表)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
/*
题目;给定一个链表,将链表旋转到右边的k个位置,其中k是非负的。
例如:
1->2->3->4->5->NULL,为K = 2,
返还4->5->1->2->3->NULL。
*/
/*
分析:先遍历一遍,得出链表长度len,注意k可能会大于len,因此k%=len。
将尾结点next指针指向首节点,形成一个环,接着往后跑len-k步,从这里断开,就是结果
*/
class Solution {
public:
    ListNode *rotateRight(ListNode *head, int k) {
        if(head==nullptr||k==0)
            return head;
        int len=1;
        ListNode *p=head;
        while(p->next){
            //遍历一遍,求出链表长度
            len++;
            p=p->next;
        }
        k=len-k%len;
         
        p->next=head;//首尾相连
        for(int step=0;step<k;step++){
            p=p->next;//接着往后跑
        }
        head=p->next;//新的首节点
        p->next=nullptr;//断开环
        return head;
    }
};

Solution 3(常规循环思路,一步一步来) 

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* lpre(ListNode *phead)
    {
        if(phead==NULL||phead->next==NULL) return phead;
        while(phead->next->next!=NULL)
          phead=phead->next;
        return phead;
    }
    ListNode *rotateRight(ListNode *head, int k) {
        if(head==NULL||head->next==NULL) return head;
        ListNode *pre=new ListNode(-1);
        pre->next=head;
        ListNode *lp=lpre(pre->next);
        for(int i=0;i<k;++k)
        {
            lp->next->next=pre->next;
            pre->next=lp->next;
            lp->next=NULL;
            lp=lpre(pre->next);
        }
        return pre->next;
    }
};

 

<think>嗯,用户想用链表实现数组的循环移位。首先,我得理解什么是循环移位。比如数组[1,2,3,4]向右移1位变成[4,1,2,3]。如果用链表的话,可能需要将末尾的节点移到头部。 那链表怎么操作呢?如果是单链表,找到尾节点可能需要遍历,这样时间复杂度是O(n)。不过数组转换成链表的话,可能需要先创建节点,然后连接起来。循环移位的话,比如右移k次,相当于把最后k个节点移到前面。但用户提到的数组循环移位,可能是指将数组元素存入链表后,进行移位操作。 需要考虑到链表的特性,比如单链表只能从头节点开始遍历,所以找到倒数第k个节点可能需要双指针或者计算长度。然后断开链表,重新连接。比如右移k位,可以将链表从第(len - k % len)的位置断开,把后半部分接到头部。 然后示例代码方面,用户可能需要看到如何用具体的语言比如Python或Java实现。比如先创建链表,然后计算有效位移,找到新头节点,调整指针。这时候要注意边界情况,比如k是0或者等于链表长度时不需要移动。 另外,用户的问题中提到的是数组的循环移位,但用链表实现。可能需要先将数组转换为链表,再进行移位操作。或者直接操作链表结构。可能还要考虑时间复杂度,比如多次移位是否高效,或者是否有更优的方法。 可能的步骤:1. 将数组转换为链表。2. 计算有效位移k,处理k大于链表长度的情况。3. 找到断开点,重新连接链表。比如,找到新头节点的前驱,断开,将原尾节点指向原头节点,新头节点成为头。 代码部分,可能需要定义链表节点类,构建链表,然后实现移位函数。例如,在Python中,可以用类表示节点,然后构建链表,接着找到断开点,调整指针。这时候要注意指针操作是否正确,避免循环引用或者断开错误。 还要考虑示例,比如输入数组[1,2,3,4,5],右移2位,得到[4,5,1,2,3]。然后代码需要展示这个过程,包括链表的构建和移位后的结果。 可能的问题:如何处理空数组或k为0的情况?如何处理k大于数组长度的情况?这时候需要取模运算,k = k % len,如果len为0则直接返回。 最后,确保代码正确,比如在断开链表时,新尾节点的next应该指向None(对于单链表),或者如果是循环链表的话可能需要不同的处理。但用户的问题可能只是普通的单链表,所以需要正确调整指针。 综上,步骤大致是:转换数组到链表,计算有效位移,找到断开点,调整指针,返回新链表。然后编写代码实现这个过程,并给出示例。</think>### 链表实现数组循环移位的方法 #### 实现思路 1. **链表构建**:将数组转换为单链表,每个元素作为链表节点 2. **有效位移计算**:通过取模运算处理超长位移,例如数组长度为$n$时,右移$k$位等价于右移$k \% n$位 3. **指针调整**:找到新链表的尾节点,将其后继节点设置为原头节点,形成循环移位效果 #### 示例代码(Python实现) ```python class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def rotate_list(arr, k): if not arr: return [] # 构建链表 head = ListNode(arr[0]) current = head for val in arr[1:]: current.next = ListNode(val) current = current.next # 计算有效位移 n = len(arr) k = k % n if k == 0: return arr # 定位新头节点前驱 fast = head for _ in range(k): fast = fast.next slow = head while fast.next: fast = fast.next slow = slow.next # 重组链表 new_head = slow.next slow.next = None fast.next = head # 转换为数组输出 result = [] curr = new_head while curr: result.append(curr.val) curr = curr.next return result # 示例:将[1,2,3,4,5]右移2位 print(rotate_list([1,2,3,4,5], 2)) # 输出 [4,5,1,2,3] ``` #### 关键点说明 1. **时间复杂度**:$O(n)$,仅需一次遍历即可完成定位操作[^1] 2. **空间优化**:直接在原链表上操作,无需额外存储空间[^4] 3. **边界处理**: - 空数组直接返回 - 位移量为0或数组长度整数倍时直接返回原数组 - 处理大位移量时通过取模运算优化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值