leetcode 61 旋转链表的思考

leetcode 61题这道题是一道中等难度题目,但是在很多公司中都有考到这道题,因此在这里尝试着借助图的方法理解一下思考过程;

方法一,寻找切分点,通过设置不同的K值,寻找规律,当k大于链表长度的时候,每次操作1个链表长度的时候相当于保持不变,所以我们可以在链表长度内考虑这个问题,因为其他的长度都可以认为有周期性。不难发现,假设链表长度L,则切分点为L - k%L ,
在这里插入图片描述
在切分点处,让前半部分的最后部分指向null,作为链表尾,后半部分的尾部指向前半部分部分的头,构成新的链表,其中过程利用快慢指针的方法,分别找到第一部分和第二部分的结尾和开头,即new_head = slowListNode.next;这一语句

//解法2 不使用循环链表
class Solution {
    public ListNode rotateRight(ListNode head, int k) {

        ListNode old_head = head; //用于计算链表长度
        ListNode new_head = head; //用于重新计算头节点

        if(head == null || k == 0)
            return head;

        int lengthOfLink = 1;
        while(old_head.next != null){
            lengthOfLink++;
            old_head = old_head.next;
        }

        int splitOfLink = lengthOfLink - k%lengthOfLink;

        if(k%lengthOfLink == 0)
            return head;

        ListNode fastListNode = head; // 快指针先找到对应的位置
        ListNode slowListNode = head; //慢指针最终指向队尾
        
        int cnt = 1;
        while(fastListNode.next != null){
            fastListNode = fastListNode.next;
            
            if(cnt < splitOfLink){
                slowListNode = slowListNode.next;
            }
            cnt++;
        }
        new_head = slowListNode.next;
        slowListNode.next = null;
        fastListNode.next = head;

        return new_head;
    }
}

方法二,用循环链表,这个时候操作更简单,先使得链表为循环链表,找到队头和队尾相邻,然后在循环k之后断开,tail部分指向队尾,新的head作为队头即可

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        
        if(head == null || k == 0) //这一步很关键,用于处理边缘情况
            return head;
        
        ListNode old_head = head;
        ListNode tail = null;
        int lengthOfLink = 1;

        while(old_head.next != null){
            old_head = old_head.next;
            lengthOfLink++;
        }
        tail = old_head;
        tail.next = head;
        old_head = head; //构建循环链表

        int splitOfLink = lengthOfLink - k%lengthOfLink;
        for(int i = 0 ;i<splitOfLink;i++){
            old_head = old_head.next;
            tail = tail.next;
        }

        tail.next = null;
        return old_head;       
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值