前端算法(持续更新)

1、最大的钻石

1楼到n楼的每层电梯口都放着一个钻石,钻石大小不一。你从电梯1楼到n楼,每层楼电梯门都会打开一次,只能拿一次钻石,问怎样才能最大的钻石?

解题思路:

这是一个经典的动态规划问题,可以使用贪心算法来解决。以下是解决这个问题的思路:

  • 定义问题

从 1 楼到 n 楼,每层楼电梯门都会打开一次,只能拿一次钻石,要找到最大的钻石。

  • 贪心算法思路

当在第 i 层楼时,如果当前钻石比之前看到的所有钻石都大,就选择当前钻石。
因为如果当前钻石是目前为止最大的,那么后面可能出现的钻石即使比当前钻石大,也不能选择了,因为只能拿一次钻石。而如果不选择当前最大的钻石,后面出现更大钻石的概率是不确定的,所以选择当前最大的钻石是一种贪心策略。

  • 具体实现步骤
  1. 初始化一个变量 max_diamond 为负无穷大,表示目前看到的最大钻石的大小。
  2. 从 1 楼开始,依次遍历每一层楼。
  3. 当到达第 i 层楼时,比较当前钻石的大小和 max_diamond 的大小。
  4. 如果当前钻石比 max_diamond 大,就更新 max_diamond 为当前钻石的大小。
  5. 最后,max_diamond 就是能拿到的最大钻石的大小。

代码实例

function maxDiamonds(n) {let num = -Infinity;for (let i = 0; i < n; i++) {num = Math.max(num, Math.floor(Math.random(i) * 100));}return num;
}
let n = 100;
console.log(maxDiamonds(n));

提示

题中包含一个隐藏条件:随机放置。说有的分析都是基于随机放置给出的。换句话说,如果放置钻石是人为干预的大小,那么本题所有分析都不成立。

2、举例说明你对尾递归的理解,已经哪些应用场景

一、对尾递归的理解

尾递归是指一个函数在执行的最后一步调用自身的递归形式。在尾递归中,递归调用是函数执行的最后一个操作,并且在调用之后不需要再进行其他操作。这使得编译器或解释器可以对尾递归进行优化,将递归调用转换为循环,从而避免了传统递归可能导致的栈溢出问题。

例如,计算阶乘的函数可以用递归和尾递归两种方式实现:

  1. 传统递归实现阶乘:
function factorial(n) {if (n === 0) {return 1;}return n * factorial(n - 1);
}

在这个传统递归实现中,每次递归调用都需要保存当前的状态到栈中,当 n 较大时,可能会导致栈溢出。复杂度为O(n)

  1. 尾递归实现阶乘:
function factorialTailRecursive(n, accumulator = 1) {if (n === 0) {return accumulator;}return factorialTailRecursive(n - 1, n * accumulator);
}

在尾递归版本中,每次递归调用时都将当前的部分结果(accumulator)传递给下一次调用,最后在 n 为 0 时返回结果。这样,编译器或解释器可以优化这种形式的递归,避免栈的不断增长。复杂度为O(1)

二、应用场景

  1. 一些数学计算和算法问题中,如果可以将问题分解为相似的子问题并且可以用尾递归形式解决,就可以使用尾递归。例如,计算斐波那契数列、求解汉诺塔问题等。
  • 数组求和
function sumArray(arr, total = 0) {if (arr.length === 0) {return total;}return sumArray(arr, total + arr.pop());}const array = [1, 2, 3, 4, 5];const result = sumArray(array);console.log(result); // 15
  • 计算斐波那契数列
function factorial(n, start=1, total=1) {if (n <= 2) {return start;}return factorial(n - 1, total, start + total);   
}
  • 数组扁平化
let arr = [1, [2, [3, [4, [5]]]]];
function flat(arr=[],result=[]) {arr.forEach(item=>{if(Array.isArray(item)){result = result.concat(flat(item,[]));}else{result.push(item);}})  return result;
}
console.log(flat(arr,[]))
  1. 在函数式编程语言中,尾递归被广泛应用,因为函数式编程强调无副作用的纯函数和递归作为主要的控制结构。例如在 Haskell、Scheme 等语言中,尾递归是一种常见的编程模式。

  2. 深度优先搜索(DFS)和广度优先搜索(BFS)算法实现中,如果需要递归遍历图或树结构,可以考虑使用尾递归优化,特别是在处理大规模数据时,以避免栈溢出。

3、去除字符串中出现次数最少的字符,不改变原字符串的顺序

实现删除字符串中出现次数最少的字符,如果出现最少的字符有多个,则把出现次数最少的字符都删除。输出删除这些单词后的字符串,字符串中的顺序保持不变

function removeLeastFrequent(str) {// 创建对象,保存key为字符,value为出现次数let obj = {};for (let i = 0; i < str.length; i++) {if (obj[str[i]]) {obj[str[i]]++;} else {obj[str[i]] = 1;}}// 找出出现次数最少的次数let minCount = Math.min(...Object.values(obj));// 删除对象obj中value为minCount的keyfor (let key in obj) {if (obj[key] === minCount) {delete obj[key];}}// 遍历原字符串,将出现次数最少的字符删除let result = '';for (let i = 0; i < str.length; i++) {if (obj[str[i]]) {result += str[i];}}return result;
}
console.log(removeLeastFrequent('aaabbbccddeeff'));

4、手写快速排序

以下是用 JavaScript 实现快速排序的代码:

function quickSort(arr) {if (arr.length <= 1) {return arr;}// 设置数组的中位数middle,pivot是middle为索引的值let middle = Math.floor(arr.length / 2);let pivot = arr[middle];let left = [];let right = [];for (let i = 0; i < arr.length; i++) {// 如果是中位数,跳过if (i === middle) {continue}// 把小于中位数的放到左边,大于的放进右边let item = arr[i];if (item < pivot) {left.push(item);} else {right.push(item);}      }// 左右分别递归转为更小的颗粒度return [...quickSort(left), pivot, ...quickSort(right)];
}
console.log(quickSort([3, 6, 8, 10, 1, 2, 1]));
}

快速排序的基本思想是:选择一个基准值(这里选择数组的第一个元素作为基准值),将数组分为两部分,小于基准值的元素放在左边,大于等于基准值的元素放在右边。然后对左右两部分分别递归地进行快速排序,最后将左、基准值、右三部分合并起来。

快速排序的时间复杂度在平均情况下为 O ( n l o g n ) O(n log n) O(nlogn),但在最坏情况下(例如数组已经有序时)为 O ( n 2 ) O(n^2) O(n2)。空间复杂度在平均情况下为 O ( l o g n ) O(log n) O(logn)(递归调用栈的深度),最坏情况下为 O ( n ) O(n) O(n)

5、洗牌算法

洗牌算法是将原数组打散,使得原数组在新数组中的位置等概率相等,也叫乱序算法

function shuffle(arr) {let len = arr.length;for (let i = len - 1; i >= 0; i--) {let randomIndex = Math.floor(Math.random() * (i + 1));[arr[i], arr[randomIndex]] = [arr[randomIndex], arr[i]];}return arr;
}

6、手写一个LRU函数

class LRU {constructor(capacity) {// 缓存的最大容量this.capacity = capacity;// 缓存的数据this.cache = new Map();}// 获取缓存数据get(key) {// 如果缓存中没有该数据,则返回falseif (this.cache.has(key)) {// 将缓存中的数据删除,再重新插入,保证最近使用的数据在最后let val = this.cache.get(key);this.cache.delete(key);this.cache.set(key, val);return val;}return false;}put(key, value) {// 如果缓存中有该数据,则删除,再重新插入if (this.cache.has(key)) {this.cache.delete(key);} else if (this.cache.size >= this.capacity) {// 另一种写法:this.cache.delete([...this.cache.keys()][0]);this.cache.delete(this.cache.keys().next().value);}this.cache.set(key, value);}
}

7、判断回文串

function isPalindrome(s) {if (typeof s !== 'string') return false;return s === s.split('').reverse().join('');
}

8、写出一个程序,接受一个由字母、数字和空格组成的字符串,和一个字符,然后输出输入字符串中该字符的出现次数。(不区分大小写字母)

牛客网的答题格式:

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;void async function () {// Write your code herelet a  = await readline();let b  = await readline();a = a.toLocaleLowerCase()b = b.toLocaleLowerCase()console.log(a.split(b).length-1)}()

9、输入一个字符串,请按长度为8拆分每个输入字符串并进行输出;长度不是8整数倍的字符串请在后面补数字0,空字符串不处理。

function fun8(str) {let len = str.length;if(len===8){console.log(str)} else if(len<8){console.log(padEnd(str))} else {let list = str.split('');let newList = [];while(list.length>0){if(list.length<8){let end = list.splice(0,list.length);newList.push(padEnd(end));} else {newList.push(list.splice(0,8).join(''));}}for(let i in newList){console.log(newList[i])}}function padEnd(msg){let n = 8-msg.length;let end = "0".repeat(n);return msg+end;}
}

10、质数因子

功能:输入一个正整数,按照从小到大的顺序输出它的所有质因子(重复的也要列举)(如180的质因子为2 2 3 3 5 )

function getZhiYinZi(str){let num = parseInt(str);let list = [];let i = 2;while (i * i <= num) {while (num % i === 0) {list.push(i);num /= i;}i++;
}
if (num > 1) {list.push(num);
}console.log(list.join(' '));
}

11、写出一个程序,接受一个十六进制的数,输出该数值的十进制表示。

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;async function hexToDecimal() {while (line = await readline()) {let hexNumber = line;console.log(parseInt(hexNumber, 16));}
}hexToDecimal();

12、合并表记录

数据表记录包含表索引index和数值value(int范围的正整数),请对表索引相同的记录进行合并,即将相同索引的数值进行求和运算,输出按照index值升序进行输出。

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;void (async function () {let n = await readline();let sets = new Map();while (n > 0) {n--;let arr = await readline();let list = arr.split(' ');let key = parseInt(list[0]),value = parseInt(list[1]);if (sets.has(key)) {let lastValue = sets.get(key);sets.set(key, lastValue + value);} else {sets.set(key, value);}}// 根据key排序const sortedMapByKey = new Map([...sets].sort((a, b) => a[0]-b[0]));for (const [key, value] of sortedMapByKey) {console.log(key, value);}
})();

13、相交链表

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

图示两个链表在节点 c1 开始相交:
在这里插入图片描述
题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。
你能否设计一个时间复杂度 O(m + n) 、仅用 O(1) 内存的解决方案?

function getIntersectionNode(headA, headB) {let lenA = 0, lenB = 0;let pa = headA;let pb = headB;while(pa){lenA++;pa = pa.next;}while(pb){lenA++;pb = pb.next;}pa = headA;pb = headB;if(lenA>lenB){let diff = lenA - lenB;while(diff>0){diff--;pa = pa.next;}} else (lenB>lenA){let diff = lenB - lenA;while(diff>0){diff--;pb = pb.next;}}while(pa && pb){if(pa === pb){return pa}pa = pa.next;pb = pb.next;}return null;
}

首先通过两个while循环分别计算headA和headB链表的长度lenA和lenB。
然后重新将pa指向headA,pb指向headB。根据lenA和lenB的大小关系,让较长的链表先走|lenA - lenB|步。
最后通过一个while循环让两个链表同时走,当pa和pb相等时,说明找到了相交节点,返回这个节点;如果循环结束都没有找到相等的节点,说明两个链表不相交,返回null。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/422152.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

让人眼前一亮的软件测试简历,收不到面试邀请算我输

不知道大家的简历是不是都写成下面这样 根据需求文档进行需求分析 熟悉业务流程&#xff0c;明确测试点 根据测试点设计测试用例 参与评审测试用例 提交和回归跟踪缺陷&#xff0c;确认修复完成之后关闭Bug 通过使用Fiddler进行抓包分析并定位前后端Bug 使用简单的SQL语…

git一个项目关联多个远程仓库

一行代码就行&#xff1a; git remote set-url origin [想要关联的远程仓库地址]想要关联哪个就切换哪个 或者不用每次切换&#xff0c;集中管理&#xff1a; Git->Manage Remotes 点击“”&#xff0c;填入Name和想要关联的远程库地址 每次push时执行命令 git push [为…

美团OC感想

OC感想 晚上十点拿到美团意向了 到家事业部。&#xff0c;日常实习没过&#xff0c;暑期实习没过&#xff0c;秋招终于意向了&#xff0c;晚上十点发的&#xff0c;整整激动到一点才睡着&#xff0c;不仅因为这是秋招的第一个意向&#xff0c;更因为这是我一直心心念念想去的地…

BUUCTF靶场[web][极客大挑战 2019]Http、[HCTF 2018]admin

目录 [web][极客大挑战 2019]Http 考点&#xff1a;Referer协议、UA协议、X-Forwarded-For协议 [web][HCTF 2018]admin 考点&#xff1a;弱密码字典爆破 四种方法&#xff1a; [web][极客大挑战 2019]Http 考点&#xff1a;Referer协议、UA协议、X-Forwarded-For协议 访问…

五款知名国内外OA系统厂商盘点,优缺点一目了然!

本文将推荐五款知名的OA系统&#xff0c;助力企业选型&#xff01; OA 系统就像是企业办公的智慧枢纽。它整合了流程审批、文档管理、沟通协作等多种功能&#xff0c;让企业的日常办公更加高效有序。就好比一个多功能的办公工具箱&#xff0c;为企业提供各种实用的工具。 然而…

研1日记9

1.理解conv1d和conv2d a. 1和2处理的数据不同&#xff0c;1维数据和图像 b. 例如x输入形状为(32,19,512)时&#xff0c;卷积公式是针对512的&#xff0c;而19应该变换为参数中指定的输出通道。 2.“SE块”&#xff08;Squeeze-and-Excitation Block&#xff09;它可以帮助模…

jenkins工具的介绍和gitlab安装

使用方式 替代手动&#xff0c;自动化拉取、集成、构建、测试&#xff1b;是CI/CD持续集成、持续部署主流开发模式中重要工具&#xff1b;必须组件 jenkins-gitlab&#xff0c;代码公共仓库服务器&#xff08;至少6G内存&#xff09;&#xff1b;jenkins-server&#xff0c;需…

无人机视角-道路目标检测数据集 航拍 8600张 voc yolo

数据集名称&#xff1a; 无人机视角-道路目标检测数据集 数据集规模&#xff1a; 图像数量&#xff1a;8600张拍摄方式&#xff1a;航拍&#xff08;使用无人机拍摄&#xff09;标注格式&#xff1a;支持VOC和YOLO格式 数据集内容&#xff1a; 该数据集由无人机从空中拍摄的…

网络安全架构师

网络安全架构师负责构建全面的安全框架&#xff0c;以保护组织的数字资产免受侵害&#xff0c;确保组织在数字化转型的同时维持强大的安全防护。 摩根大通的网络安全运营副总裁兼安全架构总监Lester Nichols强调&#xff0c;成为网络安全架构师对现代企业至关重要&#xff0c;…

源代码防泄密软件的五大特点

在数据防泄密领域&#xff0c;深信达的SDC沙盒软件以其独特的技术和创新应用&#xff0c;为源代码安全提供了强有力的保护。特别是在源代码防泄密方面&#xff0c;SDC沙盒表现出色&#xff0c;其实现方式主要包括以下几个方面&#xff1a; 1. **内核级虚拟沙盒技术**&#xff1…

Vue | Vue深入浅出——Vue中的render函数详解

1.render函数 在编写vue单文件的大多数情况下&#xff0c;我们都是使用template模板来创建HTML。然而在一些条件判断比较复杂的场景下&#xff0c;使用JavaScript去描绘HTML的生成逻辑会显得更加的简洁直观。 使用Vue官网的例子来简单说明&#xff1a; 如果自己在开发的时候…

部署Apache网站

简易部署自己的apache网站 写在前面&#xff1a;先安装好mysql&#xff0c;再来搭建站点 1.安装php [rootlocalhost ~]# yum install php -y ##安装了php&#xff0c;默认会和apache结合工作2.创建文件编写php网页代码 [rootlocalhost ~]# vim /var/www/html/index.php ##创…

linux入门到实操-1 Linux概述、诞生过程、发行版本,如何安装?

教程来源&#xff1a;B站视频BV1WY4y1H7d3 3天搞定Linux&#xff0c;1天搞定Shell&#xff0c;清华学神带你通关_哔哩哔哩_bilibili 整理汇总的课程内容笔记和课程资料&#xff0c;供大家学习交流下载&#xff1a;夸克网盘分享 本文内容为完整笔记的入门篇 概述部分历史内容…

Day9 | Java框架 | SpringBoot

Day9 | Java框架 | SpringBoot SpringBoot简介入门程序概述起步依赖 基础配置配置文件格式&#xff1a;3种yaml语法规则yaml数据读取三种格式 多环境启动配置文件参数命令行参数多环境开发控制&#xff1a;Maven & SpringBoot 多环境兼容 配置文件分类&#xff1a;4种 整合…

【JUC】15-ThreadLocal线程局部变量

1. ThreadLocal ThreadLocal提供线程局部变量。每个线程在访问ThreadLocal实例的时候都有自己的、独立的变量副本。ThreadLocal实例通常是类中的私有静态字段&#xff0c;使用它的目的是希望将状态(用户ID或事务ID)与线程关联起来。 class Saler {ThreadLocal<Integer> …

MATLAB实现Dijkstra算法和Floyd算法

目录 1、文件功能介绍 2、代码执行效果展示 3、Dijkstra算法求图的单源最短路径 4、Dijkstra fullPath的更新逻辑 5、DIjkstra算法流程图 6、Floyd算法实现图的任意两点间最短路径 7、Floyd算法流程图 8、Floyd fullPath的更新逻辑&#xff08;非递归算法&#xff09; …

labview串口大数据量报错的一种解决思路(通过tcp进行写入和读取串口数据)

因为项目要求&#xff0c;用labview给客户开发了一个上位机&#xff0c;在现场给客户调试上位机时&#xff0c;发现了几种奇怪的现象 1&#xff1a;客户样件有两路串口&#xff0c;一路串口可以多字节进行发送数据&#xff0c;一路只能单字节发送数据&#xff0c;每次单字节数据…

Pygame中获取鼠标按键状态的方法

在《Pygame中获取鼠标位置的方法》中提到&#xff0c;可以通过鼠标事件和mouse模块中的函数获取鼠标位置&#xff0c;这两种方法同样适用于获取鼠标按键状态。 1 通过鼠标点击事件获取鼠标按键状态 通过鼠标点击事件获取鼠标按键状态的代码如图1所示。 图1 鼠标点击事件获取鼠…

Gin-封装自动路由

O.0 思路一、API二、控制层三、自动路由核心四、分组路由外加中间件使用 思路 由于Java转Go直接使用的goframe框架&#xff0c;然学习Gin时觉得一个接口一个路由太麻烦&#xff0c;于是有了...1、在请求结构体中采用标签的形式&#xff0c;直接给出路由和请求方式 2、在控制层…

QXml 使用方法

VS2019 QT 编译工具链问题解决 使用winqtdeploy.exe 打包环境就可以正常运行&#xff0c;缺少某一个运行库引起的 简易使用python脚本编译运行 Python3 中的 slots 和 QT 中的 slots 宏定义重复, 放在不同的文件中进行调用可以避免 还是比较习惯从源码包引入&#xff08;方便定…