双指针算法的高级用法及示例

双指针是一种常用的算法技巧,通常用于数组或链表的操作中。在一些情况下,我们可能需要使用双指针的高级用法来解决问题。在本文中,我将介绍双指针的高级用法,并提供一些 JavaScript 示例代码来帮助你理解。

  1. 快慢指针

快慢指针是一种双指针的高级用法,它通常用于链表的操作中。快指针和慢指针同时从链表的头部开始遍历,快指针每次遍历两个节点,慢指针每次遍历一个节点。当快指针遍历到链表尾部时,慢指针指向的节点就是链表的中间节点。

这种方法的应用场景非常广泛,例如可以用来判断链表是否有环,找到链表的中间节点等等。下面是一个示例代码:

class ListNode {
  constructor(val, next = null) {
    this.val = val;
    this.next = next;
  }
}

function findMiddleNode(head) {
  let fast = head;
  let slow = head;

  while (fast !== null && fast.next !== null) {
    fast = fast.next.next;
    slow = slow.next;
  }

  return slow;
}

const node1 = new ListNode(1);
const node2 = new ListNode(2);
const node3 = new ListNode(3);
const node4 = new ListNode(4);
const node5 = new ListNode(5);

node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;

console.log(findMiddleNode(node1)); // Output: {val: 3, next: {val: 4, next: {val: 5, next: null}}}
  1. 滑动窗口

滑动窗口是一种双指针的高级用法,它通常用于字符串或数组的操作中。滑动窗口指的是一个固定大小的窗口,在字符串或数组中从左往右滑动,窗口内的内容不断发生变化。

滑动窗口可以用于解决一些字符串或数组的问题,例如找到字符串中的最长子串或最短子串等。下面是一个示例代码:

function findSubstring(s, t) {
  const result = [];
  if (!s || !t || s.length < t.length) {
    return result;
  }

  const map = new Map();
  for (let c of t) {
    map.set(c, map.has(c) ? map.get(c) + 1 : 1);
  }

  let left = 0,
    right = 0,
    count = t.length;
  while (right < s.length) {
    const d = s[right];
    if (map.has(d) && map.get(d) > 0) {
      count--;
    }
    map.set(d, map.get(d) - 1);
    right++;

    if (count === 0) {
      const leftChar = s[left];
      if (map.has(leftChar) && map.get(leftChar) >= 0) {
        count++;
      }
      map.set(leftChar, map.get(leftChar) + 1);

      if (right - left === t.length) {
        result.push(left);
      }
      left++;
    }
  }

  return result;
}

console.log(findSubstring("barfoothefoobarman", "foo")); // Output: [0, 9]

在上面的示例代码中,我们使用滑动窗口来查找字符串 s 中包含字符串 t 中所有字符的子串的起始位置。我们使用 map 来记录字符串 t 中每个字符出现的次数,并且使用 leftright 变量来记录窗口的左右边界,使用 count 变量来记录当前窗口内还需要找到多少个字符。

当我们移动右边界时,我们不断地减少 map 中对应字符的数量,如果这个字符在 map 中存在并且数量大于 0,那么说明我们已经找到了一个需要找的字符,count 就要减 1。当 count 减少到 0 时,说明当前窗口已经包含了字符串 t 中所有字符,此时我们移动左边界,直到窗口不再包含字符串 t 中所有字符,然后继续移动右边界。我们不断地维护这个过程,直到右边界到达字符串 s 的末尾。最后,我们返回所有找到的子串的起始位置。

总结

双指针是一种非常实用的算法技巧,可以用于解决许多数组和链表的问题。在一些情况下,我们可能需要使用双指针的高级用法,例如快慢指针和滑动窗口。本文介绍了双指针的高级用法,并提供了 JavaScript 示例代码,希望能够帮助你更好地理解和应用双指针算法。

你可能感兴趣的:(算法,链表,数据结构)