【前端算法入门】用双指针解题(一)


前言

双指针是解数组类型题最常见解法

比如有头尾分别有指针,然后依次向中间靠拢的双指针,
还有一种是快慢式指针,两个指针都是从左边开始,一个走的快,一个走得慢
做两道题就能明白这个概念,来吧,上题


一、验证回文串

题目如下:
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

说明:本题中,我们将空字符串定义为有效的回文串。

示例 1:
输入: "A man, a plan, a canal: Panama"
输出: true
解释:"amanaplanacanalpanama" 是回文串

示例 2:
输入: "race a car"
输出: false
解释:"raceacar" 不是回文串

这个题是入门题,很简单,思路其实就是字符串头尾两个指针分别往中间走来比较字符,上代码

var isPalindrome = function(s) {
  s = s.replace(/[^\w]/g, '').toLowerCase();
  let leftPointer = 0;
  let rightPointer = s.length - 1;
  while(rightPointer > leftPointer){
      if(s[leftPointer++] === s[rightPointer--]){
          continue;
      }else{
          return false;
      }
  }
  return true;
};

是不是很简单? 再来一道

二、删除数组中的重复项

题目如下:
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

示例 1:

输入:nums = [1,1,2]
输出:2, nums = [1,2]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
示例 2:

输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
 

提示:

0 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums 已按升序排列

思路如下:
初始状态是:
在这里插入图片描述
慢指针是i,快指针是j
如果nums[i] 等于 nums[j] 说明是相同的元素,j继续走,i还在原位
如果nums[i] 不等于 nums[j] 说明是不相同的元素,那么nums[i++] = nums[j],j继续向前走
依次类推,就相当于i指针保证它和它前面的数字都是不重复的,j就是一个遍历器
代码如下:

var removeDuplicates = function(nums) {
  let i = 0;
  for(let j = 1; j < nums.length; j++){
      if(nums[j] !== nums[i]){
          nums[i+1] = nums[j];
          i++
      }
  }
  return i + 1
};

是不是还挺简单,再来一道巩固一下

三、合并两个有序数组

题目如下:
给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。

初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。

示例 1:

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
示例 2:

输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
 

提示:

nums1.length == m + n
nums2.length == n
0 <= m, n <= 200
1 <= m + n <= 200
-109 <= nums1[i], nums2[i] <= 109

这道题大家可能很容易想到,新创建一个数组,然后分别比较这两个数组里的每一项,push进去就行了
然而因为是有序数组,第一个数组还有正好满足假如第二数组的空间,所以这里可以采取双指针来解答,从后往前遍历
代码如下:

var merge = function (nums1, m, nums2, n) {
  let len = m + n - 1;
  m--, n--;
  while (m >= 0 && n >= 0) {
    if (nums1[m] > nums2[n]) {
      nums1[len] = nums1[m--]
    } else {
      nums1[len] = nums2[n--]
    }
    len--;
  }
  if(m === -1){
    return nums1.splice(0, len+1, ...nums2.slice(0, n + 1));
  }
  if(n === -1){
    return nums1;
  }
};

总结

做完这三道题后你应该就大概了解双指针的简单用法了,希望可以帮助到你。进阶版的题目我会后续抽时间更新,大家可以关注一下,我们共同学习共同进步!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值