力扣链表问题小结

本文总结了面试中常见的链表问题,包括如何获取链表的倒数第k个元素、中间结点以及判断链表是否存在环。采用双指针策略解决,例如,倒数第k个元素可以通过让一个指针先走k步,然后两个指针同步走,直到先走的指针到达链表末尾;判断链表环则使用快慢指针,快指针每次走两步,慢指针走一步,若相遇则链表有环。
摘要由CSDN通过智能技术生成

链表问题:

面试常问问题(一般是与链表的长度和位置有关):

①获取倒数第k个元素

②获取中间位置的元素

③判断链表是否存在环

④判断环的长度

解决方法:双指针(一种思想)

①获取倒数第k个元素

题目 剑指 Offer 22. 链表中倒数第k个节点

输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点。

示例:

给定一个链表: 1->2->3->4->5, 和 k = 2.返回链表 4->5.

想法:设有两个指针 p 和 q,初始时均指向头结点。首先,先让 p 沿着 next 移动 k 次。此时,p 指向第 k+1个结点,q 指向头节点,两个指针的距离为 k 。然后,同时移动 p 和 q,直到 p 指向空,此时 q 即指向倒数第 k 个结点。

/*class Solution {
    public ListNode getKthFromEnd(ListNode head, int k) {
        //双指针,快慢指针
        ListNode fast = head, slow = head;
        for(int i = 0; i < k; i++){
            fast = fast.next;
        }

        while(fast != null){
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}*/

class Solution {
    public ListNode getKthFromEnd(ListNode head, int k) {
        //双指针,快慢指针,定义一个 变量代替第一个循环
        ListNode fast = head, slow = head;
        int t = 0;
        while(fast != null){
            //k=2,t=0, t<k,fast指针向前走
            if(t >= k)
                slow = slow.next;
            fast = fast.next;
            t++;
        }
        return slow;
    }
}
//https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/solution/mian-shi-ti-22-lian-biao-zhong-dao-shu-di-kge-j-11/

题目19. 删除链表的倒数第N个节点

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。

示例:给定一个链表: 1->2->3->4->5, 和 n = 2.当删除了倒数第二个节点后,链表变为 1->2->3->5.

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode fast = head, slow = head;
        for(int i = 0; i < n; i++){
            fast = fast.next;
        }

        //如果fast为空,表示删除的是头结点.这里也要注意,删除头节点的情况。
        if(fast == null){
            return head.next;
        }

        //注意这里的while循环中终止条件是fast.next != null,上一个是fast!=null
        while(fast.next != null){
            fast = fast.next;
            slow = slow.next;
        }
        slow.next = slow.next.next;
        return head;
    }
}

②获取中间位置的元素

题目876. 链表的中间结点

给定一个头结点为 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。

示例 1:

输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.

想法:设有两个指针 fast 和 slow,初始时指向头节点。每次移动时,fast向后走两次,slow向后走一次,直到 fast 无法向后走两次。这使得在每轮移动之后。fast 和 slow 的距离就会增加一。设链表有 n 个元素,那么最多移动 n/2 轮。当 n 为奇数时,slow 恰好指向中间结点,当 n 为 偶数时,slow 恰好指向中间两个结点的靠后一个。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode middleNode(ListNode head) {
        ListNode fast = head, slow = head;
        //注意终止条件是fast 无法向后走两次
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }
}

③判断链表是否存在环

题目141. 环形链表

给定一个链表,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

如果链表中存在环,则返回 true 。 否则,返回 false 。

想法:慢指针针每次走一步,快指针每次走两步,如果相遇就说明有环,如果有一个为空说明没有环。

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode fast = head, slow = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow)
                return true;
        }
        return false;
    }
}

 

参考链接:

https://leetcode-cn.com/problems/delete-middle-node-lcci/solution/yi-wen-gao-ding-chang-jian-de-lian-biao-wen-ti-hua/

https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/solution/mian-shi-ti-22-lian-biao-zhong-dao-shu-di-kge-j-11/

https://leetcode-cn.com/problems/middle-of-the-linked-list/solution/kuai-man-zhi-zhen-zhu-yao-zai-yu-diao-shi-by-liwei/

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值