js算法基础-01
文章目录
- 1、双指针
- 2、快慢指针
- 3、滑动指针
- 4、哈希表
- 5、汇总区间
- 6、栈
- 7、进制求和
- 8、数学
- 9、动态规划
js算法基础, 每个重要逻辑思路,做一下列举
1、双指针
- 有序数组合并:一般思路就是合并、排序,当然效率略低
- 题目1:nums1中取前m个元素,nums2中取前n个元素,组成新的有序数组,最后结果写入nums1
- 思路:双指针,两个数组各自一个指针,该位置就是未参与排序的最小值
// 一般思路
const merge = function (nums1, m, nums2, n) {const mergedArray = [...nums1.slice(0, m), ...nums2.slice(0, n)]; // 合并mergedArray.sort((a, b) => a - b); // 修改原数组,重新排序// 数组内容粘贴,一般出现在修改原数组的时候for (let i = 0; i < merged.length; i++) {nums1[i] = merged[i];}return nums1;
};console.log(merge([1, 2, 3, 0, 0, 0], 3, [2, 5, 6], 3));
// 双指针
const merge = function (nums1, m, nums2, n) {const target1 = nums1.slice(0, m); // 截取后目标数组const target2 = nums2.slice(0, n);let index1 = 0; // 每个数组一个排序位置的指针let index2 = 0;for (let i = 0; i < m + n; i++) {const num_1 = target1[index1]; // 每个数组取出的元素const num_2 = target2[index2];// 边界条件if (index1 >= m) {// 这里表示数组1已经取完了,那么剩下的全部取数组2的元素即可nums1[i] = num_2;index2++;} else if (index2 >= n) {nums1[i] = num_1;index1++;} else if (num_1 < num_2) {// 取最小值nums1[i] = num_1;index1++;} else {nums1[i] = num_2;index2++;}}return nums1;
};
console.log(merge([1, 2, 3, 0, 0, 0], 3, [2, 5, 6], 3));
- 题目2:验证回文,返回是或者否
- 思路1:当需要得到是否的时候,可以正向思考,所有满足即为true,也常见于反向思考,找出一个不符合的即为false,一般看条件苛刻程度,比如预测大部分都符合条件,那么就找出不符合的
- 思路2:for循环里自变量i就是单指针
// 快速
var isPalindrome = function (s) {const str = s.toLowerCase().replace(/[^a-z0-9]/g, "");const strR = str.split("").reverse().join("");return str === strR;
};// 双指针
var isPalindrome = function (s) {const str = s.toLowerCase().replace(/[^a-z0-9]/g, "");for (let i = 0, j = str.length - 1; i < j; i++, j--) {if (str[i] !== str[j]) return false;}return true;
};// for循环,单指针
var isPalindrome = function (s) {const str = s.toLowerCase().replace(/[^a-z0-9]/g, "");for (let i = 0; i < str.length / 2; i++) {if (str[i] !== str[str.length - 1 - i]) {return false;}}return true;
};
console.log(isPalindrome("A man, a plan, a canal: Panama")); // true
2、快慢指针
- 快慢指针:一般会出现在一个数组、一个目标数据中
- 题目:删除有序数组中的重复项
- 思路:由于有序数组中会出现重复的元素,所以慢指针指示写入的位置,快指针跳过重复的元素,直到下一个不同元素出现
var removeDuplicatesArray = [1, 1, 2];
var removeDuplicates = function (nums) {let slow = 0,fast = 1;while (fast < nums.length) {if (nums[slow] !== nums[fast]) {slow++;nums[slow] = nums[fast];}fast++;}return slow + 1;
};
console.log(removeDuplicates([1, 1, 2]), removeDuplicatesArray);
补充while 和 for的差异;可以看到差异很小,while没有初始化变量的位置,没有自增位置,只有终止逻辑;一般来说for更全面,while循环都可以改造成for循环;while适用于略微简化逻辑;
var removeDuplicates2 = function (nums) {let slow = 0,fast = 1;for (fast = 1; fast < nums.length; fast++) {if (nums[slow] !== nums[fast]) {slow++;nums[slow] = nums[fast];}}return slow + 1;
};
3、滑动指针
- 滑动指针:需要对两个指针之间的元素进行计算,比如求和
- 题目1:找出该数组nums中满足其总和大于等于 target 的长度最小的子数组,返回长度,
var minSubArrayLen = function (target, nums) {let length = nums.length,// 左指针缩小范围left = 0,// 右指针扩大范围right = 0,// sum 是动态和,有时比 target 小,有时比 target 大sum = 0,// 加1是为了断定是不是所有的元素都加起来都不够targetminLen = length + 1;for (right = 0; right < length; right++) {sum += nums[right];// 只要sum大于等于target,一直移动左指针,并得到sum和while (sum >= target) {minLen = Math.min(minLen, right - left + 1); // 计算当前窗口的长度sum -= nums[left]; // 减去左指针的值left++; // 左指针右移}}return minLen === length + 1 ? 0 : minLen;
};
console.log(minSubArrayLen(5, [1, 4, 4])); // 2
4、哈希表
- 哈希表:可以统计字符和存储数据
- 题目1:判断 ransomNote 能不能由 magazine 里面的字符构成;每个字符只能使用一次;
var canConstruct = function (ransomNote, magazine) {// 对字符的个数进行统计const magazineObj = {};// 统计for (let i = 0; i < magazine.length; i++) {const char = magazine[i];if (magazineObj[char]) {magazineObj[char]++;} else {magazineObj[char] = 1;}}// 检验for (let i = 0; i < ransomNote.length; i++) {const char = ransomNote[i];// 减到0就说明没了,返回falseif (magazineObj[char]) {magazineObj[char]--;} else {return false;}}return true;
};
console.log(canConstruct("aa", "ab")); // false
- 题目2:两数之和,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标;这里规定只有一对满足条件
- 思路:两个值,刚好可以用哈希key:value完成记录;(还有三数之和等)
var twoSum = function (nums, target) {const numsObj = {};// 统计for (let i = 0; i < nums.length; i++) {const item = nums[i];// 注意 索引0是存在配对数的,要判断undefined才准确if (numsObj[item] !== undefined) {return [numsObj[item], i];} else {numsObj[target - item] = i; // 记录配对数 对应的索引}}return [];
};console.log(twoSum([2, 7, 11, 15], 9)); // [0, 1]
5、汇总区间
汇总区间
- 题目1:给定一个 无重复元素 的 有序 整数数组 nums,返回区间汇总
var summaryRanges = function (nums) {// 区间起点指针let index = 0,result = []; // 结果数组for (let i = 0; i < nums.length; i++) {const item = nums[i];// 判断 是否 连续;不连续就要添加区间if (item !== nums[i + 1] - 1) {// 是否是单个数字;然后添加区间result.push(index === i ? `${item}` : `${nums[index]}->${item}`);index = i + 1; // 记录下一个开始的索引}}return result;
};console.log(summaryRanges([0, 1, 2, 4, 5, 7])); // ["0->2", "4->5", "7"]
6、栈
- 栈:储存了顺序结构
- 题目1:判断字符串是不是有效括号
// 方式1,所有括号都有配对的另一半,把配对子都放进去;
// 如果栈最后一个配对上了。说明他是偏向内部的完整括号,那么删除,也不再增加配对子;
// 栈为空,添加配对子;没有匹配上,添加配对子;
var isValid = function (s) {// 偶数位if (s.length % 2 !== 0 || s.length === 0) return false;const configObj = {"(": ")","{": "}","[": "]"};const stack = [];for (let i = 0; i < s.length; i++) {const char = s[i];const target = configObj[char];if (stack.length > 0) {// 检测是否配对if (stack[stack.length - 1] === char) {stack.pop();} else {// 存配对子stack.push(target);}} else {// 存配对子stack.push(target);}}return stack.length === 0;
};
console.log(isValid("([]{})")); // true
// console.log(isValid("([)")); // false
方式2,只关注左侧括号,只存储左侧括号对应的配对子
// 碰到左侧括号就放入配对子,
// 否则检查最后一个元素是否配对,
// 配对上了就删除最后一个元素
var isValid = function (s) {// 偶数位if (s.length % 2 !== 0 || s.length === 0) return false;const configObj = {"(": ")","{": "}","[": "]"};const stack = [];for (let i = 0; i < s.length; i++) {const char = s[i];const target = configObj[char];if (target) {// 放入配对子stack.push(target);} else {// 右侧括号 对应if (stack[stack.length - 1] !== char) {return false;}// 配对上了 必须删除一个stack.pop();}}return stack.length === 0;
};
console.log(isValid("([]{})")); // true
// console.log(isValid("([)")); // false
7、进制求和
- 进制求和:模仿进制
- 题目1:二进制求和
var addBinary = function (a, b) {const maxLength = Math.max(a.length, b.length);let carry = 0; // 进位let result = ""; // 结果for (let i = 0; i < maxLength; i++) {const num1 = a[a.length - 1 - i] || 0; // 取最后一位,不存在则补0const num2 = b[b.length - 1 - i] || 0;const count = parseInt(num1) + parseInt(num2) + carry; // 加法result = (count % 2) + result; // 取最后一位carry = count >= 2 ? 1 : 0; // 进位}return carry === 1 ? 1 + result : result;
};console.log(addBinary("11", "1")); // "100"
8、数学
- 题目1:数字加一,[1, 2, 9]=>[1, 3, 0]
- 熟练使用自增和自减
var plusOne = function (digits) {const length = digits.length;let carry = 1;for (let i = length - 1; i >= 0; i--) {const num = digits[i];// 处理的位置// 进制为10 检查是否进制// 不进制,原位置加数if (num + carry === 10) {digits[i] = 0;carry = 1;} else {digits[i] = num + carry;carry = 0;break; // 找到第一个不为9的就退出, 不用再加}}// 如果超出进制,在最前面再加一if (carry === 1) {digits.unshift(1);}return digits;
};
console.log(plusOne([1, 2, 9])); // [1, 2, 4]
进制时,循环索引可以自增,也可以自减;都可以定位到最后一位
const arr = [1, 2, 9];
// 自增
for (let i = 0; i < arr.length; i++) {// 处理的位置const index = length - 1 - i;const num = digits[index];
}
// 自减
for (let i = arr.length - 1; i >= 0; i--) {const num = arr[i];
}
9、动态规划
- 题目1:假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
var climbStairs = function (n) {if (n === 1) return 1;if (n === 2) return 2;let prev1 = 1;let prev2 = 2; // 两种方案 1+1,2let result = 0;// 由于最后一步只能爬1或2,// 所以只需要计算前两步的和,相当于分类讨论;// 比如假设最后一步是1,那就是在n-1的位置,爬1个台阶,// 最后一步是2,那么就在n-2的位置,爬2个台阶;// f(n) = f(n-1) + f(n-2)// 如果可以爬1\2\3,则f(n) = f(n-1) + f(n-2) + f(n-3)for (let i = 3; i <= n; i++) {result = prev1 + prev2;prev1 = prev2;prev2 = result;}return result;
};console.log(climbStairs(5)); // 8
相关文章:
js算法基础-01
文章目录 1、双指针2、快慢指针3、滑动指针4、哈希表5、汇总区间6、栈7、进制求和8、数学9、动态规划 js算法基础, 每个重要逻辑思路,做一下列举 1、双指针 有序数组合并:一般思路就是合并、排序,当然效率略低题目1:nums1中取前m个…...
了解 DeepSeek R1
了解DeepSeek R1 R1探索纯强化学习是否可以在没有监督微调的情况下学会推理的能力。 ‘Aha’ Moment 这种现象有点类似于人类在解决问题时突然意识到的方式,以下是它的工作原理: 初始尝试:模型对解决问题进行初始尝试识别:识别…...
局域网:电脑或移动设备作为主机实现局域网访问
电脑作为主机 1. 启用电脑的网络发现、SMB功能 2. 将访问设备开启WIFI或热点,用此电脑连接;或多台设备连接到同一WIFI 3. 此电脑打开命令行窗口,查看电脑本地的IP地址 Win系统:输入"ipconfig",回车后如图 4.…...
小型园区组网图
1. 在小型园区中,S5735-L-V2通常部署在网络的接入层,S8700-4通常部署在网络的核心,出口路由器一般选用AR系列路由器。 2. 接入交换机与核心交换机通过Eth-Trunk组网保证可靠性。 3. 每个部门业务划分到一个VLAN中,部门间的业务在C…...
数据分享:汽车测评数据
说明:如需数据可以直接到文章最后关注获取。 1.数据背景 Car Evaluation汽车测评数据集是一个经典的机器学习数据集,最初由 Marko Bohanec 和 Blaz Zupan 创建,并在 1997 年发表于论文 "Classifier learning from examples: Common …...
python小整数池和字符串贮存
在Python中,**小整数池**是一种优化机制,用于减少内存使用和加速小整数的创建。 ### 小整数池的工作原理 - **范围**:Python会预先创建并缓存-5到256之间的整数对象。这些对象在解释器启动时就已经创建,并且会一直驻留在内存中。…...
批量将 txt/html/json/xml/csv 等文本拆分成多个文件
我们的文本文件太大的时候,我们通常需要对文本文件进行拆分,比如按多少行一个文件将一个大的文本文件拆分成多个小的文本文件。这样我们在打开或者传输的时候都比较方便。今天就给大家介绍一种同时对多个文本文件进行批量拆分的方法,可以快速…...
Vue3 路由权限管理:基于角色的路由生成与访问控制
Vue3 路由权限管理:基于角色的路由生成与访问控制 一、核心概念 1.1 大致流程思路: 用户在登录完成的时候,后端给出一个此登录用户对应的角色名字,此时可以将这个用户的角色存起来(vuex/pinia)中,在设置路由时的met…...
LLM Agents的历史、现状与未来趋势
引言 大型语言模型(Large Language Model, LLM)近年在人工智能领域掀起革命,它们具备了出色的语言理解与生成能力。然而,单纯的LLM更像是被动的“回答者”,只能根据输入给出回复。为了让LLM真正“行动”起来ÿ…...
忘记mysql的root用户密码(已解决)
1、打开数据库可视化界面(比如MySQL workbench) 2、执行select host,user,authentication_string from mysql.user; 3、把‘authentication_string’下面的字段 复制到MD5在线解密网页中(比如md5在线解密)...
【Pandas】pandas DataFrame set_flags
Pandas2.2 DataFrame Attributes and underlying data 方法描述DataFrame.index用于获取 DataFrame 的行索引DataFrame.columns用于获取 DataFrame 的列标签DataFrame.dtypes用于获取 DataFrame 中每一列的数据类型DataFrame.info([verbose, buf, max_cols, …])用于提供 Dat…...
Vue3.2 项目打包成 Electron 桌面应用
本文将详细介绍如何将基于 Vue3.2 的项目打包成 Electron 桌面应用。通过结合 Electron 和 Vue CLI 工具链,可以轻松实现跨平台桌面应用的开发与发布。 1. 项目结构说明 项目主要分为以下几个部分: electron/main.js:Electron 主进程文件。…...
git stash pop 后反悔操作
当使用 git stash pop 应用并删除某个存储(stash)后,如果想撤销该操作(即恢复工作目录到 pop 前的状态,并重新将存储放回存储栈),可以按以下步骤操作: 1 强制丢弃所有未提交的更改&…...
Spring Boot 集成 MongoDB 时自动创建的核心 Bean 的详细说明及表格总结
以下是 Spring Boot 集成 MongoDB 时自动创建的核心 Bean 的详细说明及表格总结: 核心 Bean 列表及详细说明 1. MongoClient 类型:com.mongodb.client.MongoClient作用: MongoDB 客户端核心接口,负责与 MongoDB 服务器建立连接、…...
TypeScript面试题集合【初级、中级、高级】
初级面试题 什么是TypeScript? TypeScript是JavaScript的超集,由Microsoft开发,它添加了可选的静态类型和基于类的面向对象编程。TypeScript旨在解决JavaScript的某些局限性,比如缺乏静态类型和基于类的面向对象编程,…...
ubuntu 20.04 编译和运行SC-LeGo-LOAM
1.搭建文件目录和clone代码 mkdir -p SC-LeGo-LOAM/src cd SC-LeGo-LOAM/src git clone https://github.com/AbangLZU/SC-LeGO-LOAM.git cd .. 2.修改代码 需要注意的是原作者使用的是Ouster OS-64雷达,需要更改utility.h文件中适配自己的雷达类型,而…...
CentOS 7安装hyperscan
0x00 前言 HyperScan是一款由Intel开发的高性能正则表达式匹配库,专为需要快速处理大量数据流的应用场景而设计。它支持多平台运行,包括Linux、Windows和macOS等操作系统,并针对x86架构进行了优化,以提供卓越的性能表现。HyperSc…...
Quartz MisFire补偿机制 任务补偿 任务延迟 错过触发策略
介绍 在 Quartz 中,MisFire(错过触发)是指触发器错过了预定的触发时间,通常是由于系统延迟、任务执行时间过长或者调度器本身未能及时执行任务等原因。这种情况可能会导致任务无法按预期的时间执行。为了应对这些问题,…...
AI训练存储架构革命:存储选型白皮书与万卡集群实战解析
一、引言 在人工智能技术持续高速发展的当下,AI 训练任务对存储系统的依赖愈发关键,而存储系统的选型也变得更为复杂。不同的 AI 训练场景,如机器学习与大模型训练,在模型特性、GPU 使用数量以及数据量带宽等方面的差异ÿ…...
谢志辉和他的《韵之队诗集》:探寻生活与梦想交织的诗意世界
大家好,我是谢志辉,一个扎根在文字世界,默默耕耘的写作者。写作于我而言,早已不是简单的爱好,而是生命中不可或缺的一部分。无数个寂静的夜晚,当世界陷入沉睡,我独自坐在书桌前,伴着…...
UE5 Simulation Stage
首先将Grid2D创建出来,然后设置值,Grid2D类似于在Niagara系统中的RenderTarget2D,可以进行绘制,那么设置大小为512 * 512 开启Niagara粒子中的Simulation Stage 然后开始编写我们的自定义模块 模块很简单,TS就是Textur…...
Swift 解 LeetCode 250:搞懂同值子树,用递归写出权限系统检查器
文章目录 前言问题描述简单说:痛点分析:到底难在哪?1. 子树的概念搞不清楚2. 要不要“递归”?递归从哪开始?3. 怎么“边遍历边判断”?这套路不熟 后序遍历 全局计数器遍历过程解释一下:和实际场…...
怎样使用Python编写的Telegram聊天机器人
怎样使用Python编写的Telegram聊天机器人 代码直接运行可用 以下是对这段代码的详细解释: 1. 导入必要的库 import loggingfrom telegram import Update from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, filters, MessageHandler import log…...
Elixir语言的移动应用安全
Elixir语言的移动应用安全解析 引言 在当今的数字化时代,移动应用已经成为我们日常生活中不可或缺的一部分。从购物、社交到在线银行,几乎每一个生活领域都与移动应用紧密相连。然而,随着应用的普及,安全问题也随之而来。如何确…...
动态估算gas和gasPrice
目录 一、什么是动态估算? 二、动态估算 Gas(代码示例) ✅ 使用 Ethers.js 估算 gasLimit: 💡 发送交易时加一点 buffer: 三、动态估算 gasPrice / maxFee ✅ 获取当前 baseFee(用 provider): ✅ 搭配交易一起发送: 四、完整组合:动态估算 Gas + EIP-1559 费用…...
数据清洗
map阶段:按行读入内容,对内容进行检查,如果字段的个数少于等于11,就删除这条日志(不保留)去除日志中字段个数小于等于11的日志内容。 <偏移量,第一行的内容> → <通过刷选之后的第一行…...
增益调度控制 —— 理论、案例与交互式 GUI 实现
目录 增益调度控制 —— 理论、案例与交互式 GUI 实现一、引言二、增益调度控制的基本原理三、数学模型与公式推导四、增益调度控制的优势与局限4.1 优势4.2 局限五、典型案例分析5.1 案例一:航空飞行控制中的增益调度5.2 案例二:发动机推力控制中的增益调度5.3 案例三:化工…...
关于OEC/OEC-turbo刷机问题的一些解决方法(2)——可能是终极解决方法了
前面写了两篇关于OEC/OEC-turbo刷机问题的文章了,从刷机过程、刷机中遇到的问题,以及遇到最多但始终无法有效解决的下载boot失败的问题的剖析,最近确实也做了一些工作,虽然没有最终解决,但也算是这系列文章里面阶段性的…...
前后端接口参数详解与 Mock 配置指南【大模型总结】
前后端接口参数详解与 Mock 配置指南 一、前端请求参数类型及 Mock 处理 1.1 URL 路径参数 (Path Parameters) 场景示例: GET /api/users/{userId}/orders/{orderId}Mock.js 处理: Mock.mock(/\/api\/users\/(\d)\/orders\/(\d)/, get, (options) &g…...
瓦片数据合并方法
影像数据 假如有两份影像数据 1.全球底层影像0-5级别如下: 2.局部高清影像数据级别9-14如下: 合并方法 将9-14文件夹复制到全球底层0-5的目录下 如下: 然后合并xml文件 使得Tileset设置到最高级(包含所有级别)&…...
