Leetcode刷题记录 - 链表问题

链表问题

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

文章目录

    • 链表问题
  • 前言
  • 问题一:倒数第k个元素
  • 问题二:中间位置的结点`
  • 问题三:环形链表
  • 问题4:未完待续
  • 问题5:未完待续


前言

无法高效获取长度,无法根据偏移快速访问元素,是链表的两个劣势。然而面试的时候经常碰见诸如获取倒数第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)
Leetcode刷题记录 - 链表问题_第1张图片

//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:未完待续

你可能感兴趣的:(leetcode刷题,leetcode,java,单链表)