编程导航算法通关村第 1 关 | 链表经典问题之双指针专题笔记

876. 链表的中间结点 - 力扣(LeetCode)

第一道题目是Leetcode876题,十分经典的双指针问题之一。

什么是双指针,所谓双指针实际上就是指两个不同的变量而已,这两个变量如何变化都是由我们自己来定。

 假设我们有两个指针,A与B分别指向实例1中的①这个节点,但是A指针每次只向前走一个位置,第一次到达②,而B指针每次走两个位置,第一次到达③。

接着往前走,A到达③,B到达⑤,而B前面已经没有路可以走了,就意味着到达顶点,这时候A指针指向的就是该链表的中点。

这就是双指针的应用,实际上就是赋予两个指针不同得到运行轨迹,从而得到结果。

附上该题答案,其中A和B指针就可以用slow和fast来替代。

/**
 * 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 middleNode(ListNode head) {
            ListNode fast = head;
            ListNode slow = head;
            while (fast != null && fast.next != null) {
                slow = slow.next;
                fast = fast.next.next;
            }
            return slow;
    }
}

剑指 Offer 22. 链表中倒数第k个节点 - 力扣(LeetCode)

 这里也可以使用快慢双指针,我们先将fast 向后遍历到第 k+1 个节点, slow仍然指向链表的第一个节点,此时指针fast 与slow 二者之间刚好间隔 k 个节点。之后两个指针同步向后走,当 fast 走到链表的尾部空节点时,slow 指针刚好指向链表的倒数第k个节点。
这里需要特别注意的是链表的长度可能小于k,寻找k位置的时候必须判断fast是否为null,这是本题的关键问题之一。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public 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;
    }
}

61. 旋转链表 - 力扣(LeetCode)

利用双指针的思想,我们可以有如下思考:
因为k有可能大于链表长度,所以首先获取一下链表长度len,如果然后k=k % len,如果k == 0,则不用旋转,直接返回头结点。否则:

  1. 快指针先走k步。
  2. 慢指针和快指针一起走。
  3. 快指针走到链表尾部时,慢指针所在位置刚好是要断开的地方。把快指针指向的节点连到原链表头部,慢指针指向的节点断开和下一节点的联系。
  4. 返回慢指针指向的节点的下一个节点。
/**
 * 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 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;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值