前端算法学习,包含复杂度、双指针、滑动窗口、二叉树、堆等常见题型和方法,含leetcode例题

server/2024/9/25 3:25:52/

前端算法

学习

复杂度

  1. 时间复杂度
    代码的运行时间随着数据规模增长的趋势
  • 最好情况的时间复杂度:O(1)
  • 最坏情况的时间复杂度
  • 平均情况下的时间复杂度
  • 均摊复杂度:
  1. 空间复杂度

双指针

两个指针同向、背向移动

  1. 快慢指针
    可以用于判断链表中是否有环

  2. 背向指针

//长度为n的数组nums和目标值target,从nums选中三个整数,使它们的和与target最接近
//返回这三个数的和function threeSumClosest(nums, target) {//思路:先排序,循环target-数组里的数字,此时就变成两数之和//两个指针分别从头和尾向中间走let length=nums.length;let res=Infinity;nums.sort((a,b)=>a-b);for(let i =0;i<length;i++){//依次获取其中元素let left=i+1;let right=length-1;//变成判断两数之和与curr最接近while(left<right){let currRes=nums[i]+nums[left]+nums[right];if(Math.abs(currRes-target)<Math.abs(res-target)){res=currRes;}if(currRes<target){left++}else if(currRes>target){right--}else{return res}}}return res
}console.log(threeSumClosest([-1,2,1,-4],1))
//给你一个字符串 s 和一个字符串数组 dictionary ,找出并返回 dictionary 中最长的字符串,该字符串可以通过删除 s 中的某些字符得到。
//如果答案不止一个,返回长度最长且字母序最小的字符串。如果答案不存在,则返回空字符串。var findLongestWord = function(s, dictionary) {//双指针let left=0;let right=0;let str='';//进行判断for(let word of dictionary){//左指针在等到判断的字符串s中//右指针在等待判断的数组的字符串中left = 0;right = 0;//如果字符串长度大于原字符串,直接跳过if(word.length>s.length){continue;}while(left<s.length && right <word.length){//如果字母相同,指针移动if(s.charAt(left)===word.charAt(right)){right++;}left++;}if (right === word.length) {if (!str || (word.length > str.length || (word.length === str.length && word < str))) {str = word;}}}return str;
};console.log(findLongestWord("abpcplea",["ale","apple","monkey","plea", "abpcplaaa","abpcllllll","abccclllpppeeaaaa"]))

双指针题目思路:在循环前判断是否需要排序、遍历过程中通过双指针根据结果判断是否需要重新赋值

滑动窗口

窗口大小可变

//给定一个字符串 s ,请你找出其中不含有重复字符的 最长连续子字符串 的长度。//滑动窗口题思路:右侧指针移位->判断是否符合预期->判断左指针是否需要移位->下一次循环
function lengthOfLongestSubstring(s) {if(s.length<=1){return s.length;}let left=0;let right=1;let maxLength=0;let temp=''while(right<s.length){temp=s.slice(left,right);//如果窗口的下一个元素被包含在temp中,窗口就移动if(temp.indexOf(s[right])!=-1){left++;continue;}else{right++;maxLength=Math.max(maxLength,right-left);}}return maxLength;
}console.log(lengthOfLongestSubstring("abcabcbb"))

二叉树

常见问题是求任意两个节点的最小的公共祖先

二叉树问题要搞清楚排序的方式和当前树和节点的逻辑(处于同一侧or处于不同侧)

/*** 寻找最近公共祖先* @param {TreeNode} root * @param {TreeNode} p * @param {TreeNode} q * @returns*/
function lowestCommonAncestor(root, p, q) {//如果是null,已到达叶子节点的边界,没有找到目标//如果是p或q,说明当前节点就是最近祖先,直接返回if (root == null || root == p || root == q) return root;const left = lowestCommonAncestor(root.left, p, q);const right = lowestCommonAncestor(root.right, p, q);//如果left和right都不为空,说明p和q分别位于左右子树中,当前节点就是最近祖先if (left && right) return root;//只有一个left或right不为空,目标节点在同一侧子树中,直接返回对应子树的根节点return left || right;
}

涉及top、最大、最小的题目,用堆

//仓库管理员以数组 stock 形式记录商品库存表,
//其中 stock[i] 表示对应商品库存余量。
//请返回库存余量最少的 cnt 个商品余量,返回 顺序不限。//使用堆
//1. 原生API
// return stock.sort((a, b) => a - b).slice(0, cnt);
//2.计数排序:核心在于将输入的数据转化为key,使用空间换时间
var inventoryManagement = function(stock, cnt) {return countingSort(stock, cnt)};//计数排序
const countingSort=function(stock,cnt){let bucket=new Array()let sortedIndex=0for(let i=0;i<stock.length;i++){bucket[stock[i]]=bucket[stock[i]]+1 || 1}let res=[];for(let j=0;j<bucket.length;j++){while(bucket[j]-- > 0 && sortedIndex<cnt){res[sortedIndex++]=j}if(sortedIndex==cnt){break}}return res
}console.log(countingSort([0,2,3,6],2))
//给定一个整数数组 nums 和一个整数 k ,请返回其中出现频率前 k 高的元素。可以按 任意顺序 返回答案。var topKFrequent = function(nums, k) {let map=new Map()for(let i=0;i<nums.length;i++){if(map.get(nums[i])){map.set(nums[i],map.get(nums[i])+1)}else{map.set(nums[i],1)}}//将map转为数组,数组中每个元素也都是一个数组let entries=Array.from(map.entries())return entries.sort((a,b)=>b[1]-a[1]).slice(0,k).map(item=>item[0])
};console.log(topKFrequent([1,1,1,2,2,3],2))//使用桶排序的方法var topKFrequent = function(nums, k) {//桶排序,将数据划分到有限个桶中,再将桶进行排序//用map存储频次,用数组表达桶,频次作为数组下标let map=new Map()for(let i=0;i<nums.length;i++){if(map.has(nums[i])){map.set(nums[i],map.get(nums[i])+1)}else{map.set(nums[i],1)}}if(map.size<=k) return [...map.keys()]return bucketSort(map,k)};//桶排序
const bucketSort=(map,k)=>{let arr=[]let res=[]//map每个元素map.forEach((value,key)=>{//使用频次作为下标,将数据分配到桶中if(arr[value]){arr[value].push(key)}else{arr[value]=[key]}})for(let i=arr.length;i>=0 && res.length<k;i--){if(arr[i]){res.push(...arr[i])}}return res
}console.log(topKFrequent([1,1,1,2,2,3],2))

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

相关文章

什么是CAPTCHA?有什么用途?

一、CAPTCHA 的工作原理 CAPTCHA的核心目的是通过呈现人类可以轻松理解但计算机程序难以解决的任务&#xff0c;来阻止恶意的自动化工具。传统的CAPTCHA通过展示扭曲或模糊的文字、图片或者点击操作等&#xff0c;要求用户完成验证任务。这些任务通常需要视觉、听觉或简单的逻辑…

在Windows系统上安装的 zstd C++ 库

在Windows系统上安装的 zstd C 库 项目地址:安装步骤步骤一步骤二 效果 项目地址: https://github.com/facebook/zstd 经过观察发现,这个项目没有CMakeLists.txt,只有Makefile,但是Makefile在windows系统下没有什么用, 所以说,常规的方式安装不可取了 安装步骤 步骤一 往下…

html+css学习

html 元素 html元素是HTML的根元素&#xff0c;一个文档只能有一个&#xff0c;其他所有元素都是其后代元素 html有一个属性为lang&#xff0c;其作用是&#xff1a; 帮助语言合成工具确定要使用的发音帮助翻译工具确定要使用的翻译规则 当属性lang“en”则表示告诉其浏览器…

重修设计模式-结构型-门面模式

重修设计模式-结构型-门面模式 门面模式为子系统提供一组统一的接口&#xff0c;定义一组高层接口让子系统更易用 门面模式&#xff08;Facade Pattern&#xff09;&#xff0c;也称作外观模式&#xff0c;主要用于为复杂的子系统提供一个统一的、更简洁的接口&#xff0c;使得…

grep命令如何实现正则表达式搜索?

grep 命令支持使用正则表达式&#xff08;Regular Expression&#xff0c;简称 regex&#xff09;进行搜索 以下是一些使用正则表达式的基本示例&#xff1a; 搜索包含 “example” 的行&#xff1a; grep "example" file.txt搜索以 “abc” 开头的行&#xff1a; g…

[深度学习]神经网络

1 人工神经网络 全连接神经网络 2 激活函数 隐藏层激活函数由人决定输出层激活函数由解决的任务决定: 二分类:sigmoid多分类:softmax回归:不加激活(恒等激活identify)2.1 sigmoid激活函数 x为加权和小于-6或者大于6,梯度接近于0,会出现梯度消失的问题即使取值 [-6,6] ,…

报错error: RPC failed,curl 16 Error in the HTTP2 framing layer解决方法

error: RPC failed&#xff1b; curl 16 Error in the HTTP2 framing layerfatal: expected flush after ref listing 问题描述&#xff1a; git pull origin main报错error: RPC failed&#xff0c;curl 16 Error in the HTTP2 framing laye 解决方法1&#xff1a; git con…

如何使用Postman搞定带有token认证的接口实战!

现在许多项目都使用jwt来实现用户登录和数据权限&#xff0c;校验过用户的用户名和密码后&#xff0c;会向用户响应一段经过加密的token&#xff0c;在这段token中可能储存了数据权限等&#xff0c;在后期的访问中&#xff0c;需要携带这段token&#xff0c;后台解析这段token才…