leetcode:15. 三数之和(双指针解法)

本题解法:

第一次上手这道题的时候,真的是无从下手,只能想到暴力枚举,导致时间复杂度很大。
本题使用了双指针的解法。初步看,无法看到如何使用双指针解题(刚上手的时候也想到了这个,尝试套用),由于双指针通常操作的是有序数组,因此,先使用了sort()排序,将数组变为有序的。接下来就使用一个外层for循环去遍历这个数组,且每次循环确定一个num,内部的while循环只需要找到两者的,内部while循环主要就是为了找到除了num自身值以外的符合条件的选项。

下面为详细说明:

首先定义leftright两个指针,left指针的初始位置始终为i+1,也就是指向num的下一位;right指针的初始位置为数组的最后一位。
接下来求出*left*right(这里的’*'直接理解为指向数组的值,相当于解引用吧,下面都是),接下来比较add-num的大小;
add == -num,那么这个就是符合条件的值,直接pushresult返回值内;
add<-num,那么就要执行left++,因为开头已经将数组进行排序,从左到右,依次变大;
add>num,那么就要执行 ‘right–’,将add值变小些。
以上便是while循环中主要执行的逻辑,但是不要急,到此还没有结束,别忘了题目上还有说明不要出现重复值,还要进行如下判断
1.在外层for循环中,如果当前值和前一个值相等,则直接跳过。

       //判断去重
      if (i - 1 >= 0 && nums[i] == nums[i - 1]) {
        continue;
      }

2.在内层while循环中,如果出现nums[left]nums[left-1]相同,则直接跳过。

    //去重(左边界判断)
    if (left - 1 > i && nums[left] == nums[left - 1]) {
      left++;
      continue;
    }

2.在内层while循环中,如果出现nums[right]nums[left+1]相同,则直接跳过。

   //去重(右边界判断)
      if (right + 1 < nums.length && nums[right] == nums[right + 1]) {
        right--;
        continue;
      }

代码展

var threeSum = function (nums) {
  //创建返回值数组
  let result = [];
  //本题需要采用双指针算法思想解题,而双指针思想通常是对有序数组进行操作,所以第一步是先将数组进行排序
  //注意,使用slice是直接将原有nums赋值一份,防止排序中影响原数组
  nums = nums.slice().sort((a, b) => a - b);
  console.log(nums);
  //使用外层for循环来选择一个数num,那么本题就转换为了求两数之和为-num的问题
  for (let i = 0; i < nums.length - 2; i++) {
    console.log("第" + i + "轮");
    let num = nums[i];
    //定义一个指针指向num的后一位,即为 i+1,另外一个指针指向数组的末端
    let left = i + 1;
    let right = nums.length - 1;
    //判断去重
    if (i - 1 >= 0 && nums[i] == nums[i - 1]) {
      continue;
    }
    //内部循环结束的条件
    while (left < right) {
      //计算两个指针指向数字的和
      let add = nums[left] + nums[right];
      console.log(nums[i], nums[left], nums[right], add);
      //去重(左边界判断)
      if (left - 1 > i && nums[left] == nums[left - 1]) {
        left++;
        continue;
      }
      //去重(右边界判断)
      if (right + 1 < nums.length && nums[right] == nums[right + 1]) {
        right--;
        continue;
      }
      if (add == -num) {
        console.log("合格", nums[i], nums[left], nums[right]);
        result.push([nums[i], nums[left], nums[right]]);
        //左指针向右移动 继续匹配
        left++;
        right--;
      }
      //如果和小于所需值,就左指针右移,增大add值
      if (add < -num) {
        left++;
      }
      //如果和小于所需值,就右指针左移,缩小add值
      if (add > -num) {
        right--;
      }
    }
  }
  console.log(result);
  return result;
};

threeSum([-1, 0, 1, 2, -1, -4]);


你可能感兴趣的:(leetcode,算法,职场和发展)