Leetcode刷题记录 - 链表问题

链表问题

总结常出现的几种链表问题


前言

无法高效获取长度,无法根据偏移快速访问元素,是链表的两个劣势。然而面试的时候经常碰见诸如获取倒数第k个元素,获取中间位置的元素,判断链表是否存在环,判断环的长度等和长度与位置有关的问题。这些问题都可以通过灵活运用双指针来解决。

参考链接:https://leetcode-cn.com/problems/linked-list-cycle/solution/yi-wen-gao-ding-chang-jian-de-lian-biao-wen-ti-h-2/

问题一:倒数第k个元素

大体思路是,设置两个指针q,p,初始时刻同时指向头节点,首先p指针移动k次,这时p指针指向第k+1个结点,之后两个指针同时移动,当p指针指向空时,q指针指向倒数第k个结点。

代码如下(示例):

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public int kthToLast(ListNode head, int k) {
        ListNode p = head;
        ListNode q = head;
        for(int i=0;i<k;i++)
        {
            p = p.next;
        }
        while(p!=null)
        {
            p=p.next;
            q=q.next;
        }
        return q.val;
    }
}

问题二:中间位置的结点`

使用快慢指针,fast移动两部每次,slow每次移动一步,当fast.next为空时,如果链表有单数个结点,那么指向的就是中间节点,如果是偶数个结点,那么指向的就是中间位置考前的那一个结点,代码参考上一个。

问题三:环形链表

会询问是否有环,环的长度,环的位置等
是否有环:
1.可以用hash表中元素唯一性来实现
2.另外可以使用快慢指针,如果有环那么快慢指针一定会相遇
环的长度:
基于是否有环的基础上,当快慢指针第一次相遇之后再次移动,使用计数器,下一次相遇时移动的次数就是环的长度。
环的位置:
使用快慢指针,下图来自leetcode。
可以进行推导,核心为快指针移动步数始终为慢指针的二倍。
2*(a+b) = a+(n-1)b+n*c
继而得到 a=c+(n-1)(b+c)
![![在这里插入图片描述]](https://img-blog.csdnimg.cn/20201214133606505.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZlbmdxaXNoaW1lbmc=,size_16,color_FFFFFF,t_70

//hash 实现
/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode p = head;
        Set<ListNode> _hash = new HashSet<ListNode>();
        while(p!=null)
        {
            if(_hash.contains(p))
            {
                return p;
            }
            else
            {
                _hash.add(p);
                p=p.next;
            }
        }
        return null;
    }
}

时间复杂度和空间复杂度都是O(n),但是使用hash表比较直观

//快慢指针实现
/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while(fast!=null)
        {
            slow = slow.next;
            if(fast.next!=null)
            {
                fast = fast.next.next;
            }
            else
            {
                return null;
            }
            if(fast == slow)
            {
                ListNode cur = head;
                while(cur!=slow)
                {
                    cur=cur.next;
                    slow=slow.next;
                }
                return cur;
            }
        }
        return null;
    }
}

时间复杂度是O(N),空间复杂度为O(1)。

问题4:未完待续

问题5:未完待续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值