Javascript算法——双指针法移除元素、数组去重、比较含退格字符、有序数组平方

server/2024/10/18 9:32:49/

数组移除元素(保证数组仍连续

暴力求解法(两层for循环),length单词拼写错误❌二次嵌套for的length设置

/*** @param {number[]} nums* @param {number} val* @return {number}*/
var removeElement = function(nums, val) {let length=nums.length;for(i=0;i<length;i++){const currVal=nums[i];if(currVal===val){for(k=i;k<length-1;k++){nums[k]=nums[k+1]}i--;//往前移了一个,有要从此位置开始遍历检测length--; }}return length;
};

双指针法(一层for循环)

没碰到要删除的值一样快,碰上要删除的值”慢指针就落后(不++)“

return位置❌ ,核心基础

/*** @param {number[]} nums* @param {number} val* @return {number}*/
var removeElement = function(nums, val) {let slow=0;for(fast=0;fast<nums.length;fast++){if(nums[fast]!==val){nums[slow++]=nums[fast];}}return slow;
};

数组去重

function removeDuplicatesWithTwoPointers(arr) {  // 首先对数组进行排序(如果数组未排序)  arr.sort((a, b) => a - b);  // 初始化两个指针(索引)  let left = 0;  // 遍历数组,从第二个元素开始(索引1)  for (let right = 1; right < arr.length; right++) {  // 如果当前元素与左指针指向的元素不同,则将其保留在数组中  // 并移动左指针到该位置  if (arr[right] !== arr[left]) {  //先移动指针,后替换值left++;  // 可选:如果你想要在原地修改数组,可以使用splice来替换元素  // arr.splice(left, 0, arr[right]); // 这行代码实际上是不必要的,因为我们可以直接赋值  arr[left] = arr[right]; // 直接赋值即可,因为我们已经移动了left指针  }  // 如果相同,则忽略当前元素(右指针继续移动)  }  // 截断数组,只保留去重后的部分  arr.length = left + 1;  return arr;  
}  // 示例  
const originalArray = [4, 4, 2, 5, 1, 2, 3, 3];  
const uniqueArray = removeDuplicatesWithTwoPointers(originalArray);  
console.log(uniqueArray); // 输出: [1, 2, 3, 4, 5]
------------------------------------------------------------------
/*** @param {number[]} nums* @return {number}*/
var removeDuplicates = function(nums) {let pre=0;for(i=1;i<nums.length;i++){if(nums[pre]!==nums[i]){pre++;nums[pre]=nums[i];}}return pre+1;
};

移动零

在移除元素的基础上加了一个zeroIndex而已

/*** @param {number[]} nums* @return {void} Do not return anything, modify nums in-place instead.*/
var moveZeroes = function(nums) {let zeroCounts=0;let currentIndex=0;for(let i=0;i<nums.length;i++){if(nums[i]!=0){nums[currentIndex]=nums[i];currentIndex++}else{zeroCounts++;}}for(j=0;j<zeroCounts;j++){nums[currentIndex+j]=0;}return nums;
};

比较含退格的字符串

使用栈的思路

  1. 定义函数
    首先,你需要定义一个函数,比如叫 backspaceCompare,它接收两个字符串 s 和 t 作为参数。

  2. 处理字符串
    对于每个字符串(s 和 t),你需要编写一个辅助函数(比如叫 processString)来模拟退格字符的行为。这个函数将遍历字符串,并使用一个栈(或数组,因为在这里栈的功能可以通过数组轻松模拟)来存储非退格字符。

    遍历完成后,栈中剩余的字符就是模拟退格字符后的字符串。

    • 遍历字符串时,如果当前字符不是 #,则将其压入栈中。
    • 如果当前字符是 #,则从栈中弹出一个字符(如果栈不为空)。
  3. 比较结果
    使用上述辅助函数分别处理 s 和 t,得到两个处理后的字符串。然后,比较这两个字符串是否相等。

  4. 返回结果
    根据比较的结果,返回 true 或 false

/*** @param {string} s* @param {string} t* @return {boolean}*/
var backspaceCompare = function(s, t) {let sArr=process(s);let tArr=process(t);return sArr.toString()===tArr.toString()
};
function process(str){let arr=[];for(let i=0;i<str.length;i++){if(arr[i]!=='#'){arr.push(arr[i]);}else{arr.pop();}}return arr;
}

双向指针

/*** @param {string} s* @param {string} t* @return {boolean}*/
var backspaceCompare = function(s, t) {//#数量let sSkipNum=0;let tSkipNum=0;let i=s.length-1;let j=t.length-1;while(true){while(i>=0){if(s[i]==="#"){sSkipNum++;i--;}else{//有#号抵消一个数,移动指针[key]if(sSkipNum>0){sSkipNum--;i--;}else{break;}}}while(j>=0){if(t[j]==="#"){tSkipNum++;j--;}else{if(tSkipNum>0){tSkipNum--;j--;}else{break;} }}//有一方处理完就退出if(i<0||j<0)break;//字符不同if(s[i]!==t[j]){return false;}//移动指针,继续比较i--;j--;}if(i==-1&&j==-1){//同时处理完,且字符已经相等了return true;}else{return false;}
};

有序数组平方

定义左右指针和一个索引(从大递减),比较两个数的平方,移动指针更新索引 

function sortedSquares(nums) {  const n = nums.length;  const result = new Array(n); // 创建一个与输入数组相同大小的结果数组  let left = 0; // 左指针  let right = n - 1; // 右指针  let index = n - 1; // 结果数组的索引,从后往前填充  while (left <= right) {  const leftSquare = nums[left] * nums[left];  const rightSquare = nums[right] * nums[right];  if (leftSquare > rightSquare) {  result[index] = leftSquare;  left++;  } else {  result[index] = rightSquare;  right--;  }  index--;  }  return result;  
}  // 示例用法  
const nums = [-4, -1, 0, 3, 10];  
const squaredNums = sortedSquares(nums);  
console.log(squaredNums); // 输出: [0, 1, 9, 16, 100]

在JavaScript算法中,双向指针(也称为双指针或对指针)技术是一种常用的技巧,特别适用于处理需要同时从数组或字符串的两端或中间向某个方向移动指针的问题。这种方法通常能够减少空间复杂度,并且有时也能降低时间复杂度。以下是一些常见的应用场景:

  1. 数组或字符串中的两数之和
    • 给定一个已排序的数组(或字符串)和一个目标和,使用双向指针从两端向中间遍历,找到两个数(或字符)使它们的和等于目标和。这种方法的时间复杂度为O(n)。
  2. 回文检测
    • 判断一个字符串是否是回文。可以使用两个指针,一个从字符串的开头开始,另一个从字符串的末尾开始,然后向中间移动,比较对应位置的字符是否相同。
  3. 容器中的水量
    • 给定n个非负整数表示每个柱子的高度,计算在这些柱子之间能够接到的雨水总量。这个问题可以通过使用双向指针和栈来解决。
  4. 合并两个有序数组
    • 将两个有序数组合并成一个有序数组。可以使用两个指针分别指向两个数组的开头,然后比较当前指针所指的元素,将较小的元素添加到结果数组中,并移动相应的指针。
  5. 最长公共子序列(LCS)
    • 虽然通常使用动态规划来解决LCS问题,但双向指针也可以用于一些特定形式的LCS问题,特别是在与字符串匹配相关的问题中。
  6. 滑动窗口
    • 双向指针技术可以与滑动窗口技术结合使用,以解决一些需要维护一个固定大小的窗口并计算窗口内元素的问题。
  7. 移除元素使数组有序
    • 给定一个数组,其中每个元素都是某个范围内的整数。要求移除尽可能少的元素,使得剩余的元素按非递减顺序排列。这个问题可以通过使用双向指针和贪心策略来解决。
  8. 链表中的两数相加
    • 给定两个表示非负整数的链表,每个节点包含一个数字。这些数字以逆序的方式存储,并且每个节点只能存储一个数字。将这两个数相加并以链表的形式返回它们的和。这个问题可以通过使用双向指针(或更准确地说是两个游标)来遍历两个链表并构建结果链表。

请注意,双向指针的应用场景不仅限于上述例子,它可以根据问题的具体需求进行灵活应用。在解决问题时,重要的是要识别出是否可以通过同时从两个方向遍历数据来简化问题或提高效率。


http://www.ppmy.cn/server/132734.html

相关文章

数据结构-排序算法

基于交换的排序算法 快速排序&#xff1a; 最优情况 最优情况下&#xff0c;每次找到的参考轴把数据分成均匀的两半&#xff0c;最后应该是一个平衡二叉树状态&#xff1b;二叉树的层数&#xff08;logn&#xff09;即为递归需要进行的次数&#xff0c;并且每轮递归结束时&…

asp.net core _ViewStart.cshtml 和 _ViewImports.cshtml

_ViewStart.cshtml asp.net mvc 就出现了 》》/Views/ViewStart.cshtml _ViewStart.cshtml 是默认模板&#xff0c;当页面没有指定 Layout 时&#xff0c;会自动调用此默认模板‌&#xff0c;如果要取消 在当页面设定 &#xff08;如下&#xff09;&#xff0c;则表示 当前页面…

【C语言】多文件工程程序,自定义头文件

包含一个主程序&#xff0c;也就是main函数的书写。包含一个头文件的声明文件。包含一个头文件具体函数的实现文件。 注意一点&#xff1a;所有的文件放到一个文件夹没用&#xff0c;必须添加到同一个项目中去才行。 否则 会提示无法识别用户自定义头文件中的函数。 main.c…

进程和线程

文章目录 什么是线程/进程进程进程的特点&#xff1a; 线程线程的特点&#xff1a; 进程与线程的区别&#xff1a;实际应用 什么是线程/进程 进程是资源分配最小单位&#xff0c;线程是程序执行的最小单位 进程 进程是程序的一次执行过程&#xff0c;它是操作系统进行资源分…

[新电脑整理工作]

git 安装python安装 工作需要同时安装py2,和py3,故用anconda 软件&#xff0c;下载并安装成功后 1、conda create -n py2 python2.7 conda cerete -n py3 python3.8 2、安装成功后用VScode直接切换不同环境就可以&#xff08;原本旧电脑就不可用&#xff0c;可能是vscode 版本有…

Jmeter如何进行多服务器远程测试?

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 JMeter是Apache软件基金会的开源项目&#xff0c;主要来做功能和性能测试&#xff0c;用Java编写。 我们一般都会用JMeter在本地进行测试&#xff0c;但是受到单…

怎么把音频的速度调慢?6个方法调节音频速度

怎么把音频的速度调慢&#xff1f;调慢音频速度不仅可以帮助我们更好地捕捉细节&#xff0c;还能让我们在分析和学习时更加从容。这对于音乐爱好者来说&#xff0c;尤其有助于理解复杂的旋律和和声&#xff0c;使学习过程变得更加高效。而在语言学习中&#xff0c;放慢语速则能…

ICM20948 DMP代码详解(86)

接前一篇文章:ICM20948 DMP代码详解(85) 上一回开始解析inv_icm20948_ctrl_enable_sensor函数中最为核心的inv_enable_sensor_internal函数,解析了前边的两段代码,本回继续往下解析。为了便于理解和回顾,再次贴出inv_enable_sensor_internal函数源码,在EMD-Core\sources…