前端手撕题总结篇(算法篇——来自Leetcode牛客)

链表

在这里插入图片描述

指定区域反转

找到区间(头和为 for循环当**时)->反转链表(返回反转过后的头和尾)->连接

function reverseBetween( head ,  m ,  n ) {//preEnd&cur&nextStart  cur.next断开if(m===n)return head;const vHeadNode=new ListNode(0);vHeadNode.next=head;let preEnd=null;let cur = vHeadNode;for(let i=0;i<n;i++){if(i===m-1)preEnd=cur;cur=cur.next;}let nextStart =cur.next;cur.next=null;const [start,end]=reverseList(preEnd.next);preEnd.next=start;end.next=nextStart;return vHeadNode.next;
}
function reverseList(head){const vHeadNode=new ListNode(-1);vHeadNode.next=head;let cur=head;while(cur){const next=cur.next;cur.next=vHeadNode.next;vHeadNode.next=cur;cur=next;}return [vHeadNode.next,head];
}

每K个一组反转(★★★)

指针preEnd&cur->while(cur)->curStart=cur;curEnd=preEnd,if(!preEnd)return vHead.next->反转连接-》cur=nextStart&preEnd=End(翻转过后)

function reverseKGroup(head, k) {// write code hereconst vHeadNode=new ListNode(-1);vHeadNode.next=head;let preEnd=vHeadNode;let cur=head;while(cur){let curStart=cur;let curEnd=preEnd;for(let i=0;i<k;i++){curEnd=curEnd.next;if(!curEnd)return vHeadNode.next;}let nextStart=curEnd.next;curEnd.next=null;const [start,end]=reverseSubList(curStart);preEnd.next=start;end.next=nextStart;cur=nextStart;preEnd=end;}return vHeadNode.next;
}
//反思一下自己吧!!!简单但请仔细
function reverseSubList(head) {let dummyNode = new ListNode(0);let cur = head;while (cur) {let next = cur.next;cur.next = dummyNode.next;dummyNode.next = cur;cur = next;}return [dummyNode.next, head];
}

合并K个已排序链表(★★★)

基础:合并两个已排序链表->归并排序

export function mergeKLists(lists: ListNode[]): ListNode {// // write code here// //nlogn --->归并// //拆开// //返回的是ListNode不是数组类型,ts编译会报错!太好了// if(lists.length<=1) return lists[0];// const mid=Math.floor(lists.length/2);// const left=mergeKLists(lists.slice(0,mid));// const right=mergeKLists(lists.slice(mid));// return merge(left,right);if(lists.length<=1)return lists[0];const mid =Math.floor(lists.length/2);const left = mergeKLists(lists.slice(0,mid));const right=mergeKLists(lists.slice(mid));return merge(left,right);
}function merge(pHead1:ListNode, pHead2:ListNode) {const dummyNode = new ListNode(0);let cur = dummyNode;while (pHead1 && pHead2) {if (pHead1.val < pHead2.val) {cur.next = pHead1;pHead1 = pHead1.next;} else {cur.next = pHead2;pHead2 = pHead2.next;}cur = cur.next;}cur.next=pHead1?pHead1:pHead2;return dummyNode.next;
}

基础

//双指针判断是否有环
function hasCycle( head ) {if(!head)return false;//起点相同let fast=head;let slow=head;//&&这里出错while(fast&&slow&&fast.next){//先跳后判断fast=fast.next.next;slow=slow.next;if(fast===slow)return true;}return false;}
//链表环的入口
function EntryNodeOfLoop(pHead)
{if(!pHead||!pHead.next)return null;let fast=pHead;let slow=pHead;while(fast&&slow&&fast.next){fast=fast.next.next;slow=slow.next;if(fast===slow){fast=pHead;//这!!!while(fast!==slow){fast=fast.next;slow=slow.next;}return fast;}}
}
//倒数第	K个节点
function FindKthToTail( pHead ,  k ) {// write code here//测试案例II,求长度!const genLen=(curNode)=>{let count=0;while(curNode){curNode=curNode.next;count++;}return count;}const len=genLen(pHead);//判断是否合理!!!if(k>len)return null;let fast=pHead,slow=pHead;while(k--){fast=fast.next;}//这条件!!!while(fast){fast=fast.next;slow=slow.next;}return slow;
}
//删除链表的倒数第n个节点(虚拟头结点)
function removeNthFromEnd( head ,  n ) {// write code herelet vHeadNode=new ListNode(0);vHeadNode.next=head;let fast=vHeadNode;let slow=vHeadNode;while(n--){fast=fast.next;}// //若不借助虚拟节点// //这一步真是太关键了// if(quick == null){//     return head.next// }//key:此处判断条件就不一样 fast.next&&slow.next!!!while(fast.next){fast=fast.next;slow=slow.next;}slow.next=slow.next.next;return vHeadNode.next;
}
//两链表第一个公共节点
export function FindFirstCommonNode(pHead1: ListNode, pHead2: ListNode): ListNode {//另一种思路:求长度差+先走+while相等退出返回//循环条件应该是当两个指针没有相遇时继续循环,即while(cur1 !== cur2)。//这样,当它们相等时(无论是相交节点还是都为null)就退出循环并返回cur1(此时等于cur2)if(!pHead1||!pHead2)return null;let cur1=pHead1;let cur2=pHead2;while(cur1!==cur2){cur1=cur1?cur1.next:pHead2;cur2=cur2?cur2.next:pHead1;}return cur2;
}

链表相加(★★★)

先反转+链表相加(大数相加)+反转结果

function addInList( head1 ,  head2 ) {// write code hereconst dummyNode=new ListNode(0);let cur=dummyNode;let reversedList1=reverseList(head1);let reversedList2=reverseList(head2);let carry=0;while(reversedList1||reversedList2||carry){let val1=reversedList1?reversedList1.val:0;let val2=reversedList2?reversedList2.val:0;const sum=val1+val2+carry;const digit=sum%10;const node =new ListNode(digit);carry=Math.floor(sum/10);cur.next=node;cur=cur.next;//!!!移动指针!!!链表相加肯定要移动指针!!!if(reversedList1)reversedList1=reversedList1.next;if(reversedList2)reversedList2=reversedList2.next;}return reverseList(dummyNode.next);
}
function reverseList(head){let vHeadNode=new ListNode(0);let cur=head;while(cur){let next=cur.next;cur.next=vHeadNode.next;vHeadNode.next=cur;cur=next;}return vHeadNode.next;
}

单链表排序

分治(归并)排序
key:找链表中点(需借助虚拟头结点)->返回条件->合并(两个已排序链表)

function sortInList( head ) {// write code here//分治if(!head||!head.next)return head;const middle=findMiddle(head);let right=middle.next;middle.next=null;const leftHead=sortInList(head);const rightHead=sortInList(right);const merge=(leftHead,rightHead)=>{const dummyNode=new ListNode(0);let cur=dummyNode;let head1=leftHead;let head2=rightHead;while(head1&&head2){if(head1.val>head2.val){cur.next=head2;head2=head2.next;}else{cur.next=head1;head1=head1.next;}cur=cur.next;}cur.next=head1?head1:head2;return dummyNode.next;}return merge(leftHead,rightHead);
}
function findMiddle(head){//要虚拟头结点!!!!这一个函数错了,导致整个通过不了!!!const dummyNode=new ListNode(0);dummyNode.next=head;let fast=dummyNode;let slow=dummyNode;while(fast&&fast.next){fast=fast.next.next;slow=slow.next;}return slow;
}

回文链表

找链表中节点(同上)-》反转左侧链表-》比较,若有不对等返回false

export function isPail(head: ListNode): boolean {// write code hereconst middle=findMiddle(head);let leftHead=head;let rightHead=middle.next;middle.next=null;const reverseList=(head:ListNode|null):ListNode=>{const dummyNode=new ListNode(0);let cur=head;while(cur){const next=cur.next;cur.next=dummyNode.next;dummyNode.next=cur;cur=next;}return dummyNode.next;}let reverseRightHead=reverseList(rightHead);while(leftHead&&reverseRightHead){if(leftHead.val!==reverseRightHead.val)return false;leftHead=leftHead.next;reverseRightHead=reverseRightHead.next;}return true;}
function findMiddle(head:ListNode):ListNode{const dummyNode=new ListNode(0);dummyNode.next=head;let fast=dummyNode;let slow=dummyNode;while(fast&&fast.next){fast=fast.next.next;slow=slow.next;}return slow;
}

链表奇偶排序

指针:odd、even&evenHead
条件:even&&even.head
返回:head

function oddEvenList( head ) {if(!head||!head.next)return head;// write code herelet odd=head;//奇数let even=head.next;//偶数let evenHead=even;//记录偶节点的头结点//终止条件:偶节点&偶节点.next不为空!!!!//even&&even.nextwhile(even&&even.next){odd.next=even.next;odd=odd.next;even.next=odd.next;even=even.next;}odd.next=evenHead;return head;
}

删除重复元素

I->cur=head

function deleteDuplicates( head ) {// write code herelet cur=head;//链表靠着时next指针,不要想着还计算长度什么!while(cur){while(cur.next&&cur.val===cur.next.val){cur.next=cur.next.next;}cur=cur.next;}return head;}

II(♥)

  1. 虚拟头结点
  2. 找到if(cur.next.val=cur.next.next.val)并存储至temp,内部while(cur.next&&cur.next.val=temp)删除节点
  3. 否则就是cur=cur.next
export function deleteDuplicates(head: ListNode): ListNode {// // write code here// const vHeadNode=new ListNode(0);// vHeadNode.next=head;// let cur=vHeadNode;// let temp=0;// while(cur.next&&cur.next.next){//     if(cur.next.val===cur.next.next.val){//         temp=cur.next.val;//         //相同的节点都跳过//         while(cur.next&&cur.next.val===temp){//             cur.next=cur.next.next;//         }//     }else{//         //其他节点就向后移//         cur=cur.next;//     }// }// return vHeadNode.next;const vHeadNode=new ListNode(0);vHeadNode.next=head;//虚拟头结点,解决第一个和第二个元素就相同的情况let cur=vHeadNode;let temp=0;while(cur.next&&cur.next.next){if(cur.next.val===cur.next.next.val){temp=cur.next.val;while(cur.next&&cur.next.val===temp){cur.next=cur.next.next;}}else{cur=cur.next;}}return vHeadNode.next;
}

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

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

相关文章

从Excel到工时管理系统:企业如何选择更高效的工时记录工具?

还在为手工统计员工工时而头疼吗&#xff1f;月末堆积如山的Excel表格、反复核对的数据、层出不穷的差错&#xff0c;这些问题正在拖慢企业的发展步伐。8Manage工时管理系统发现&#xff0c;传统手工记录不仅耗费大量人力&#xff0c;更让宝贵的工时数据难以转化为有效的管理决…

Java设计模式之《命令模式》

目录 1、介绍 1.1、命令模式定义 1.2、对比 1.3、典型应用场景 2、命令模式的结构 2.1、组成部分&#xff1a; 2.2、整体流程 3、实现 3.1、没有命令模式 3.2、命令模式写法 4、命令模式的优缺点 前言 java设计模式分类&#xff1a; 1、介绍 1.1、命令模式定义 命…

【动态规划算法】路径问题

什么是动态规划算法动态规划&#xff08;Dynamic Programming&#xff0c;简称 DP&#xff09;是一种通过分解复杂问题为重叠子问题&#xff0c;并存储子问题的解以避免重复计算&#xff0c;从而高效求解具有特定性质&#xff08;重叠子问题、最优子结构&#xff09;问题的算法…

Java基本技术讲解

一、基础语法三要素 暂时无法在飞书文档外展示此内容 &#x1f511; 黄金法则​&#xff1a;每个变量都要声明类型&#xff01;二、程序逻辑控制&#xff08;游戏行为核心&#xff09; 条件判断&#xff1a;if-else - “岔路口选择” // 捡到金币逻辑 if (isTouching(Coin.clas…

【网络基础2】路由器的 “两扇门”:二层接口和三层接口到底有啥不一样?

目录 前言:路由器不是只有 “插网线的口” 一、先搞懂一个基础:路由器是 “网络交通枢纽” 二、二层接口:“小区内部的单元门”,只认 “住户身份证” 1. 啥是二层接口? 2. 用 “小区内部串门” 理解二层接口 步骤 1:手机打包数据,写上 “收件人身份证” 步骤 2:二…

MLIR TableGen

简介 TableGen 是一种领域特定语言&#xff08;DSL&#xff09;&#xff0c;TableGen 的设计目标是允许编写灵活的描述&#xff0c;并将记录的通用特性提取出来&#xff0c;从而减少重复代码并提高代码的可维护性。 TableGen的工作流程&#xff1a; 前端解析&#xff1a; Ta…

2、docker容器命令 | 信息查看

1、命令总览命令作用docker ps查看运行中的容器&#xff08;-a查看所有容器&#xff09;docker logs [CONTAINER]查看容器日志&#xff08;-f实时追踪日志&#xff09;docker inspect [CONTAINER]查看容器详细信息&#xff08;JSON格式&#xff09;docker stats [CONTAINER]实时…

【MySQL】MySQL中锁有哪些?

一、按照粒度分类&#xff1a; 粒度越小&#xff0c;并发度越高&#xff0c;锁开销越大。 1.全局锁&#xff1a; 作用&#xff1a; 锁定整个MySQL实例(所有数据库)。适用场景&#xff1a; 全库逻辑部分。(确保备份期间数据的一致性。)实现方式&#xff1a; 通过 FLUSH TABLES W…

语义分割--deeplabV3+

根据论文网络结构图讲一下&#xff1a;网络分为两部分&#xff1a;encoder和decoder部分。 Encoder&#xff1a;DCNN就是主干网络&#xff0c;例如resnet&#xff0c;Xception&#xff0c;MobileNet这些&#xff08;主干网络也要使用空洞卷积&#xff09;&#xff0c;对dcnn的结…

Azure DevOps 中的代理

必知词汇 深入研究 Azure DevOps 中的代理之前需要掌握的基本概念: 代理:Azure DevOps 中的代理是一个软件组件,负责执行流水线中的任务和作业。这可能包括数据中心内的物理服务器、本地或云端托管的虚拟机,甚至是容器化环境。这些代理可以在各种操作系统和环境中运行,例如…

AUTOSAR进阶图解==>AUTOSAR_SRS_ADCDriver

AUTOSAR ADC驱动详解 基于AUTOSAR标准的ADC驱动模块需求规范分析目录 ADC驱动模块概述 关键概念定义 ADC驱动架构 ADC驱动在AUTOSAR分层架构中的位置ADC驱动的主要职责 ADC驱动配置结构 通用配置(AdcGeneral)硬件单元配置(AdcHwUnit)通道配置(AdcChannel)通道组配置(AdcChanne…

宝马集团与SAP联合打造生产物流数字化新标杆

在德国雷根斯堡的宝马工厂&#xff0c;每57秒就有一辆新车下线。这座工厂不仅是汽车制造的基地&#xff0c;更是宝马集团向SAP S/4HANA云平台转型的先锋项目。通过“RISE with SAP”计划&#xff0c;宝马将该工厂的运营系统全面迁移至SAP S/4HANA Cloud Private Edition&#x…

Go 语言实战:构建一个高性能的 MySQL + Redis 应用

引言&#xff1a;为什么是 Go MySQL Redis&#xff1f;在现代后端技术栈中&#xff0c;Go MySQL Redis 的组合堪称“黄金搭档”&#xff0c;被广泛应用于各种高并发业务场景。Go 语言&#xff1a;以其卓越的并发性能、简洁的语法和高效的执行效率&#xff0c;成为构建高性能…

Excel超级处理器,多个word表格模板中内容提取到Excel表格中

在职场中&#xff0c;很多人习惯在word里插入表格&#xff0c;设计模板&#xff0c;填写内容&#xff0c;一旦有多个word文件需要整理在excel表格中&#xff0c;最常见的工作方式就是每个word文件打开&#xff0c;复制&#xff0c;粘贴到excel表格里&#xff0c;这样的工作方式…

前端工程化:ES6特性

本文为个人学习笔记整理&#xff0c;仅供交流参考&#xff0c;非专业教学资料&#xff0c;内容请自行甄别 文章目录一、let与var1.1、越狱问题1.2、变量的重复声明1.3、变量提升问题二、解构2.1、数组解构2.2、对象解构2.3、方法解构三、链判断四、参数默认值五、箭头函数六、模…

大屏项目展示

一、项目克隆与基础操作 我们参考的项目 互联网设备可视化平台---IofTV-Screen: 🔥一个基于 vue、datav、Echart 框架的物联网可视化(大屏展示)模板,提供数据动态刷新渲染、屏幕适应、数据滚动配置,内部图表自由替换、Mixins注入等功能,持续更新.... 将次项目克隆到本…

基于R语言地理加权回归、主成份分析、判别分析等空间异质性数据分析实践技术应用

在自然和社会科学领域有大量与地理或空间有关的数据&#xff0c;这一类数据一般具有严重的空间异质性&#xff0c;而通常的统计学方法并不能处理空间异质性&#xff0c;因而对此类型的数据无能为力。以地理加权回归为基础的一系列方法&#xff1a;经典地理加权回归&#xff0c;…

【Flask 基础 ①】 | 路由、参数与模板渲染

0 序言 Flask 是 Python 生态中一款轻量级 Web 框架&#xff0c;以简洁、灵活著称。 学习 Flask 的意义在于&#xff1a; 快速开发&#xff1a;通过少量代码即可搭建功能完整的 Web 应用&#xff1b;理解原理&#xff1a;其设计清晰体现了 Web 框架的核心逻辑&#xff0c;如路由…

wordpress登陆前登陆后显示不同的顶部菜单

在WordPress中让“未登录”和“已登录”用户看到不同的顶部菜单&#xff0c;最干净、最安全、最可维护的做法是&#xff1a; 在同一个菜单位置(themelocation)里&#xff0c;根据is_user_logged_in()动态切换菜单。 下面给出三种常见实现方式&#xff0c;按推荐程度排序。任选…

【昇腾推理PaddleOCR】生产级部署方式

已知的在昇腾上推理Paddle OCR有三种方法&#xff1a; 概要&#xff1a; PyTorch官方提供了昇腾插件包&#xff0c;安装后虽然可以支持PytorchOCR和PaddlePaddle的推理任务&#xff0c;但性能较低。换句话说&#xff0c;PaddlePaddle框架层面支持了昇腾&#xff0c;但具体到某个…