小白刷力扣之双指针

286 阅读2分钟

前言

作为一个刚刚开始接触算法的小白,在刚刚开始的leetcode之路上,选择了方法较为多的数组作为起点。在经过不少题目的摧残之后,发现很多题目都用到了一种相同的方法--双指针,因此这篇文章诞生的目的就是总结一下近期认识到的双指针用法,加以巩固。

双指针是什么

在我的理解里,双指针就是下标,索引的概念,而不是指在数据结构中的指针概念,双指针就是在遍历的过程中使用两个指针进行动态的扫描。

双指针的用法

双指针就是定义两个指针进行遍历,因此我们可以根据不同的题目需求去设置两个指针的起始位置、运动速度、方向等。双指针也多用于数组,链表等链式结构。

两层循环

如leetcode的第一题两数之和,在一个数组中找到两个数的和为目标值。 在这个题目中,就可以使用到双指针最常用的方法双指针遍历
定义:外层循环指针 i, 内层循环指针 j,需要得到的值target,得到的数组arr
i的初始值设置为0,j的初始值设置为 i + 1,
如何进行循环,判断是否存在 arr[i] + arr[j] == target
存在就输出 [i, j], 否则就不存在。

    for(let i=0;i<nums.length;i++){
        for(let j=i+1;j<nums.length;j++){
            if(nums[i] + nums[j] == target){
                return [i,j]
            }
        }
    }
    return []
};

对撞指针

对撞指针就是使双指针中指针的初始化位置,一个指针在数组的头部,一个指针在数组的尾部。让它们不断的向中间靠拢,直到碰撞到一起(下标相同),多用于有序数组

var numRescueBoats = function(people, limit) {
  people.sort((a, b) => (a - b));
  var num = 0
  let left = 0
  let right = people.length - 1
  while (left <= right) {
    if ((people[left] + people[right]) <= limit) {
      left++
    }
    right--
    num++
  }
  return num
};

快慢指针

快慢指针就是设置指针的移动速度,让一个指针缓慢移动,一个指针快速移动,比如快指针一次走两步,慢指针一次走一步。快慢指针在针对成环问题很有效果,如果一个链表成环,那么两个指针终有一天会重合。

leetcode141环形链表,给定一个头节点,判断在链表中是否有环。

这道题目就很适合使用快慢指针的方法,设置快指针一次走两步,慢指针一次走一步,这样如果链表中存在环,那么快指针一定会有先进入环内,并且在环内不断绕圈,等待着慢指针的到来,与其相遇。如果不存在环,慢指针就永远追不上快指针,它们也不会相遇,因此判断两个指针是否相遇就能判断是否成环。

    if(head == null || head.next == null){
        return false;
    }
    let fast = head.next;
    let slow = head;
    while(fast != slow){
        if(fast == null || fast.next == null){
            return false;
        }
        fast = fast.next.next;
        slow = slow.next;
    }
    return true;
};

总结

关于双指针的方法还有很多,应该针对不同的问题去设置指针的各个属性。碰到有序数组时应该优先考虑双指针,以减少时间复杂度和空间复杂度。