当前位置: 首页 > news >正文

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

前端算法题

学习

复杂度

  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))

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 提升动态数据查询效率:应对数据库成为性能瓶颈的优化方案
  • 基于OpenMV的智能小车图像识别与跟踪系统设计
  • python:django项目知识点02——搭建简易授权码核销系统
  • 前端分段式渲染较长文章
  • WebGL渲染与创建2D内容
  • Redis-分片集群
  • 关于在vue2中给el-input等输入框的placeholder加样式
  • 一些关于线程之间协作的心得
  • 基于微信小程序的美食外卖管理系统
  • npm install --force or --legacy-peer-deps
  • 1网络安全的基本概念
  • LeetCode从入门到超凡(二)递归与分治算法
  • C++中move和forword的区别
  • spring自定义属性编辑器
  • SOCKS5代理为何比HTTP代理更快?
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • __proto__ 和 prototype的关系
  • 【108天】Java——《Head First Java》笔记(第1-4章)
  • CSS居中完全指南——构建CSS居中决策树
  • vue自定义指令实现v-tap插件
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 从零搭建Koa2 Server
  • 多线程事务回滚
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 构建工具 - 收藏集 - 掘金
  • 回顾2016
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 排序算法学习笔记
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 适配mpvue平台的的微信小程序日历组件mpvue-calendar
  • 网络应用优化——时延与带宽
  • 为什么要用IPython/Jupyter?
  • 详解移动APP与web APP的区别
  • 移动端 h5开发相关内容总结(三)
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • Linux权限管理(week1_day5)--技术流ken
  • 从如何停掉 Promise 链说起
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • #AngularJS#$sce.trustAsResourceUrl
  • #define,static,const,三种常量的区别
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • #考研#计算机文化知识1(局域网及网络互联)
  • #设计模式#4.6 Flyweight(享元) 对象结构型模式
  • ${ }的特别功能
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • (附源码)计算机毕业设计高校学生选课系统
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (三)centos7案例实战—vmware虚拟机硬盘挂载与卸载
  • (三)uboot源码分析
  • (十一)图像的罗伯特梯度锐化
  • (一)【Jmeter】JDK及Jmeter的安装部署及简单配置
  • (译)2019年前端性能优化清单 — 下篇
  • .NET Core SkiaSharp 替代 System.Drawing.Common 的一些用法
  • .NET 反射的使用
  • .NET/C# 判断某个类是否是泛型类型或泛型接口的子类型