编辑
2024-08-20
undefined
00

目录

方法: 双指针

以下是有关双指针相关算法的题目与题解。

移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

我的解法

js
var removeElement = function (nums, val) { for (let i = 0; i < nums.length; i++) { if (nums[i] === val) { nums.splice(i, 1) i-- } } return nums.length }

然而 splice 操作时间复杂度为 O(n),并且每次删除一个元素都会导致数组的重新排序。因此在算法解题中应尽量避免使用数组自带方法操作

方法: 双指针

js
var removeElement = function (nums, val) { let left = 0, right = nums.length while (left < right) { if (nums[left] === val) { nums[left] = nums[right - 1] right-- } else { left++ } } return left }

如果题目有要求排序的话,不如将符合条件(nums[i] !== val)的元素移到数组头部,这样就不需要排序了。

js
var removeElement = function (nums, val) { const n = nums.length let left = 0 for (let right = 0; right < n; right++) { if (nums[right] !== val) { nums[left] = nums[right] left++ } } return left }

删除有序数组中的重复项

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。返回 k 。

我的解法

js
var removeDuplicates = function (nums) { const counter = {} let count = 0 for (let i = 0; i < nums.length; i++) { counter[nums[i]] = (counter[nums[i]] || 0) + 1 if (counter[nums[i]] > 2) { continue } else { nums[count] = nums[i] count++ } } return count }

思路很清晰,就是用一个计数对象来计数,然后遍历数组,如果计数大于 1,就跳过,否则就赋值。不过我这里引入了 counter 对象,因此空间复杂度为 O(k),其中 k 表示不同元素的数量。

如果以我这个思路去解决 删除有序数组中的重复项 II 解决题目就会特别容易,只需要将 > 1 换成 1 即可。不过题目要求 不使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

并且通常哈希计数针对无序而言,而题目所给定的数据又有序,因此想要解得好就需要采用其他方案。

方法: 双指针

由于题目声明输入 升序排列 的数组,因此采用快慢双指针来判断后一个元素是否等于前一个,如果不相等则说明是不同的元素,慢指针(不同数字次数)加一,快指针继续遍历。

js
var removeDuplicates = function (nums) { const n = nums.length let fast = 1, slow = 1 while (fast < n) { if (nums[fast] !== nums[fast - 1]) { nums[slow] = nums[fast] ++slow } ++fast } return slow }

判断子序列

我的解法(失败)

既然判断子序列,那我就把无关元素删除,然后判断最后元素是否包含即可。

js
var isSubsequence = function (s, t) { t = t.replace(new RegExp(`[^${s}]`, 'g'), '') return t.includes(s) }

然而假设输入数据为

s = "leetcode" t = "yyyyyleeeytcode"

处理后数据为

s = "leetcode" t = "leeetcode"

很显然这里 includes 无法判断子序列,因此这种思路不可行。

方法: 双指针

js
var isSubsequence = function (s, t) { let i = 0, j = 0 while (i < s.length && j < t.length) { if (s[i] === t[j]) { i++ } j++ } return i === s.length }

两数之和 II - 输入有序数组

方法: 双指针

js
function twoSum(nums, target) { let left = 0 let right = nums.length - 1 while (left < right) { const sum = nums[left] + nums[right] if (sum === target) { return [left, right] } if (sum > target) { right-- } else if (sum < target) { left++ } } }

本文作者:任浪漫

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明出处!