算法通关村第一关——链表经典问题之双指针专题笔记

1.寻找中间结点

示例1
输入:[1,2,3,4,5]
输出:此列表中的结点3
示例2:
输入:[1,2,3,4,5,6]
输出:此列表中的结点4

Java代码

public static ListNode middleNode(ListNode head) {
    ListNode slow = head, fast = head;
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    return slow;
}

对于寻找链表中间结点的问题,我们可以用快慢指针来解决,一个slow指针和一个fast指针一起遍历链表,slow走一步,fast走两步,当fast在处于链表的尾部的时候,slow也就处于中间的位置了。

这里还有一个问题要思考,当链表是偶数的时候,是返回示例2里的3还是4?还有就是通常当数组也是偶数的时候,是返回示例2里的3还是4?为什么会这样?

答案:链表返回4,而数组返回3。

原因:

链表是一种非连续的数据结构,元素通过指针相互连接。在链表中,要查找中间值通常需要遍历链表,采用快慢指针的方式。快指针每次移动两步,慢指针每次移动一步,当快指针到达链表末尾时,慢指针就会指向链表的中间节点。这种算法会导致返回偏后的中间值,因为慢指针在快指针到达末尾之前总是略落后于快指针。

而数组是一个连续的数据结构,每个元素都有一个索引,可以通过索引直接访问。在数组中,中间值通常是位于中间索引的元素。对于包含偶数个元素的数组,有两个中间值,一个位于索引位置 n/2 - 1,另一个位于索引位置 n/2,其中 n 是数组的长度。通常情况下,返回偏前的中间值是因为编程语言中的数组索引从0开始计数。

2.寻找倒数第k个元素

我们可以使用快慢指针,让fast先遍历到k+1的结点位置,slow仍然在第一个位置,此时slow和fast就相差了k个结点,此时slow和fast同步走,当fast到达链表的结尾空结点时,slow所指向的就是倒数第k个元素。有个需要注意的问题是链表的长度可能小于k,所以寻找k位置的时候需要判断k位置是否为null。

Java代码

public static ListNode getKthFromEnd(ListNode head, int k) {
    ListNode fast = head;
    ListNode slow = head;

    while (fast != null && k > 0) {
        fast = fast.next;
        k--;
    }
    while (fast != null) {
        fast = fast.next;
        slow = slow.next;
    }
    return slow;
}

3.旋转链表

Leetcode61.先看题目要求:给你一个链表的头节点head,旋转链表,将链表每个节点向右移动k个位置。
示例1:
输入:head=[1,2,3,4,5],k=2
输出:[4,5,1,2,3]

先用双指针策略找到倒数K的位置,也就是{1,2,3}和{4,5}两个序列,之后再将两个链表拼接
成{4,5,1,2,3}就行了。具体思路是:
因为k有可能大于链表长度,所以首先获取一下链表长度en,如果然后k=k%Ien,如果k==0,则不用
旋转,直接返回头结点。否则:
1.快指针先走k步。
2.慢指针和快指针一起走。
3.快指针走到链表尾部时,慢指针所在位置刚好是要断开的地方。把快指针指向的节点连到原链表头部,慢指针指向的节点断开和下一节点的联系。
4.返回结束时慢指针指向节点的下一节点。

public static ListNode rotateRight(ListNode head, int k) {
    if (head == null || k == 0) {
        return head;
    }
    ListNode temp = head;
    ListNode fast = head;
    ListNode slow = head;
    int len = 0;
    while (head != null) {
        head = head.next;
        len++;
    }
    if (k % len == 0) {
        return temp;
    }
    while ((k % len) > 0) {
        k--;
        fast = fast.next;
    }
    while (fast.next != null) {
        fast = fast.next;
        slow = slow.next;
    }
    ListNode res = slow.next;
    slow.next = null;
    fast.next = temp;
    return res;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值