day05 双指针、快慢指针

200 阅读3分钟

双指针和快慢指针是常用的算法技巧,特别是在面试和竞赛中,常常会遇到需要用到这两种指针的问题。本文将介绍这两种指针的概念、应用场景和刷题技巧,并给出一些Java代码示例。

1. 双指针

双指针是一种常见的算法思想,它的基本思路是使用两个指针分别指向不同的位置,然后根据题目要求移动指针,最终找到需要的解或者某种特定的规律。双指针常用于处理数组或者链表等数据结构。

双指针的应用场景非常广泛,如判断回文字符串、求两数之和等问题。下面是一个求两数之和的问题示例:

public int[] twoSum(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left < right) {
        int sum = nums[left] + nums[right];
        if (sum == target) {
            return new int[] {left + 1, right + 1};
        } else if (sum < target) {
            left++;
        } else {
            right--;
        }
    }
    return null;
}

在上述代码中,使用了两个指针left和right分别指向数组的第一个和最后一个元素。然后根据题目要求移动指针,最终找到需要的解。

2. 快慢指针

快慢指针也是一种常见的算法思想,它的基本思路是使用两个指针,一个指针移动速度较快,另一个指针移动速度较慢,然后根据题目要求移动指针,最终找到需要的解或者某种特定的规律。快慢指针常用于处理链表等数据结构。

快慢指针的应用场景也非常广泛,如判断链表是否有环、求链表中间节点等问题。下面是一个求链表中间节点的问题示例:

public 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就到达了链表的中间位置。

3. 刷题技巧

在刷题时,双指针和快慢指针是非常常用的算法思想。下面是几个刷题技巧:

  • 仔细分析题目要求,选择合适的指针类型。
  • 注意边界情况和特殊情况,如数组为空、链表为空、链表只有一个节点等。
  • 在处理链表时,可以使用快慢指针来判断是否有环,快指针每次移动两个位置,慢指针每次移动一个位置,如果快指针和慢指针相遇,那么就说明有环。
  • 在处理数组时,可以使用双指针来求两数之和、三数之和等问题,通过移动指针来找到需要的解。
  • 在处理字符串时,可以使用双指针来判断回文字符串、最长回文子串等问题。

4. Java代码示例

下面是一个求两数之和的问题的Java代码示例:

public int[] twoSum(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left < right) {
        int sum = nums[left] + nums[right];
        if (sum == target) {
            return new int[] {left + 1, right + 1};
        } else if (sum < target) {
            left++;
        } else {
            right--;
        }
    }
    return null;
}

下面是一个求链表中间节点的问题的Java代码示例:

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