算法学习day22

一、函数的独占时间

给你一个进程数量,和运行日志。运行日志log的格式为:进程id:(start/end):运行时间

其中一个进程运行时可以被另一个优先级较高的进程抢占cpu。求每个进程独占cpu的时间。

输入:n = 2, logs = ["0:start:0","1:start:2","1:end:5","0:end:6"]
输出:[3,4]
思路:

利用栈的特点(栈反应了各个进程使用cpu的情况);

1.当遇到start的时候,可能是新的进程优先级更高,也可能是此时没有进程使用cpu。

   1.1 如果是优先级更高的进程抢占了,那么栈一定不为空,更新之前进程的独立运行时间

   1.2 如果栈为空,就说明之前没有进程使用cpu 那么直接入栈 更新startTime

2. 遇到end就结束了,更新当前进程的独立运行时间。

代码:
class Solution {public int[] exclusiveTime(int n, List<String> logs) {int[] time=new int[n];Stack<Integer> stack=new Stack<>();int startTime=-1;for(String log:logs){String[] split=log.split(":");int id=Integer.parseInt(split[0]);int curTime=Integer.parseInt(split[2]);if(split[1].equals("start")){
//栈不为空 说明是优先级更高的进程抢占了,需要更新之前进程独立运行的时间if(!stack.isEmpty())time[stack.peek()]+=curTime-startTime;stack.push(id);//入栈startTime=curTime;}else{//如果遇到了"end"符 就说明该进程结束了time[id]+=curTime-startTime+1;stack.pop();startTime=curTime+1;}}return time;}
}

链表

二、删除链表的倒数第N个节点(双指针)二刷

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

思路:

定义slow、fast指针。如何让slow指针移动到要删除节点的前一个节点。eg:如上图所示,先让fast移动n下,也就是先把5,4移动了。然后同时移动1 2 3 。这时fast下一个必为空。拿这个当作判断条件,就可以把slow移动到删除结点的前一个结点

class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dummyHead=new ListNode();dummyHead.next=head;//设置虚拟头节点ListNode fast=dummyHead;ListNode slow=dummyHead;for(int i=0;i<n;i++)fast=fast.next;while(fast.next!=null){fast=fast.next;slow=slow.next;}slow.next=slow.next.next;return dummyHead.next;}
}

三、扁平化多级双向链表(类似于插入节点)

你会得到一个双链表,其中包含的节点有一个下一个指针、一个前一个指针和一个额外的 子指针 。给定链表的头节点 head ,将链表 扁平化 ,以便所有节点都出现在单层双链表中。

题意: 

跟插入节点类似,但插入节点一般是插入单个节点。这个要插入多个节点。

如果有子节点的话,下一个节点就是子节点,如果没有子节点,下一个节点就是next。

思路:

1.判断是否有子节点,如果没有,下一个节点就是next

2.如果有子节点,下一个节点就是如何规则的孩子节点们...,孩子节点们的下一个节点是该节点之前的下一个节点。

if(head.child!=null)Node temp=head.next;Node child=flatten(head.child);head.next=child;child.prev=head;head.child=null;

while(child.next!=null)child=child.next; child.next=temp; if(temp!=null)temp.prev=child;

 代码:
class Solution {public Node flatten(Node head) {Node dummyHead =new Node();dummyHead.next=head;while(head!=null){if(head.child!=null){//存储head节点之前的下一个节点Node temp=head.next;//获取孩子节点Node child=flatten(head.child);head.next=child;child.prev=head;head.child=null;//孩子节点变成下一个节点 因此孩子节点消失//将head节点之前的下一个节点放到孩子最后一个节点后面while(child.next!=null)child=child.next;child.next=temp;if(temp!=null)temp.prev=child;}else{head=head.next;}}return dummyHead.next;        }
}

四、反转链表II(一次遍历穿针引线/双指针?)

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

一次遍历穿针引线法:

第一次:1->3->2->4->5

第二次:1->4->3->2->5

思路:

pre、cur、next三个指针。pre指针一直不变,next=cur.next;所以三个节点中只有一个cur是在主动变化。大概思路就是:每次先将cur.next=next.next,然后将next.next改为pre.next。也就是将这个节点提前。pre.next=next;

工作流程:

eg:1-2-3-4-5 left:2 right:4

1.pre=1 cur=2 next=3

2.首先将3从2的next中去除(因为3要提前),变成2-4-5

3.然后pre和next相连,变成1-3

4.next和cur相连  1-3-2-4-5

代码:
class Solution {public ListNode reverseBetween(ListNode head, int left, int right) {ListNode dummyHead=new ListNode();dummyHead.next=head;ListNode pre=dummyHead;for(int i=0;i<left-1;i++)pre=pre.next;//pre就是要第一个反转节点的前一个节点ListNode cur=pre.next;ListNode next=new ListNode();for(int i=0;i<right-left;i++){//每次更新next 随着cur的变化而变化next=cur.next;//先将next在cur.next中省去(因为next要提前)cur.next=next.next;//将next提前到至pre.nextpre.next=next;//连接next和curnext.next=cur;}return dummyHead.next;}
}
双指针翻转?
思路:

1.首先找到翻转部分第一个节点的前一个结点pre;并且找到翻转部分的最后一个结点rightNode

2.然后截取中间部分,ListNode leftNode=pre.next;ListNode curr=rightNode.next;

要反转的部分是:以leftNode为起点到以rightNode为结尾的这一部分。然后把两边部分的结点断开:pre.next=null;rightNode.next=null;

3.然后放到reverseLinkedList(leftNode)进行翻转

4.翻转之后,rightNode翻到前面,pre.next=rightNode; 然后leftNode翻到后面,leftNode.next=curr;

5.返回 return dummyHead.next;

代码:
class Solution {public ListNode reverseBetween(ListNode head, int left, int right) {ListNode dummyHead=new ListNode();dummyHead.next=head;ListNode pre=dummyHead;//第一步 找到prefor(int i=0;i<left-1;i++)pre=pre.next;//pre就是要第一个反转节点的前一个节点//第二步 找到反转范围内最右边的结点ListNode rightNode=dummyHead;//右边的节点for(int i=0;i<right;i++){rightNode=rightNode.next;}//第三步切断出一个子链表(截取链表)ListNode leftNode=pre.next;ListNode curr=rightNode.next;pre.next=null;rightNode.next=null;//反转 以leftNode为起点 以rightNode为结尾的这段范围中的reverse(leftNode);//拼接pre.next=rightNode;leftNode.next=curr;return dummyHead.next;}public void reverse(ListNode head){ListNode dummyHead =new ListNode();dummyHead.next=head;ListNode pre=dummyHead;ListNode cur=head;while(cur!=null){ListNode temp=cur.next;cur.next=pre;pre=cur;cur=temp;}}
}

 五、旋转链表

给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。

思路:

找到翻转后新的头节点,然后将新头节点之前的结点都放到新节点中最后一个结点之后。

首先要计算出链表的长度length,然后计算出新头节点前一个的位置index;index=length-(k%length)。如果从虚拟头结点开始数的话,这个位置应该是前一个结点的位置。

然后把前面那些结点连到后面就行了。

代码:
class Solution {public ListNode rotateRight(ListNode head, int k) {if(head==null||head.next==null||k==0)return head;ListNode dummyHead=new ListNode();dummyHead.next=head;//计算链表的长度ListNode cur=dummyHead;int length=0;while(cur!=null&&cur.next!=null){cur=cur.next;length++;}if(k%length==0)return head;//找到旋转后的首结点 length-(k%length)+1;ListNode pre=dummyHead;//旋转首节点的前一个结点int index=length-(k%length);//示例1中4的位置for(int i=0;i<index;i++){pre=pre.next;}ListNode realHead=pre.next;pre.next=null;ListNode rightNode=realHead;while(rightNode.next!=null){rightNode=rightNode.next;}rightNode.next=dummyHead.next;dummyHead.next=realHead;return dummyHead.next;}
}

六、两数相加II

思路:

和两数相加I类似,1.先把两个链表反转 2.然后相加 3.最后将结果反转返回

代码:
class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {ListNode dummyHead1=new ListNode();dummyHead1.next=reverseLinkedList(l1);ListNode addHead=dummyHead1;ListNode dummyHead2=new ListNode();dummyHead2.next=reverseLinkedList(l2);ListNode dummyHead3=new ListNode();ListNode cur=dummyHead3;int carry=0;while(dummyHead1.next!=null||dummyHead2.next!=null){int num1=dummyHead1.next==null?0:dummyHead1.next.val;int num2=dummyHead2.next==null?0:dummyHead2.next.val;System.out.println("num1:"+num1+" num2:"+num2);cur.next=new ListNode((num1+num2+carry)%10);cur=cur.next;carry=(num1+num2+carry)/10;if(dummyHead1.next!=null)dummyHead1=dummyHead1.next;if(dummyHead2.next!=null)dummyHead2=dummyHead2.next;}if(carry!=0)cur.next=new ListNode(carry);return reverseLinkedList(dummyHead3.next);}public ListNode reverseLinkedList(ListNode head){ListNode dummyHead=new ListNode();dummyHead.next=head;ListNode slow=null;ListNode fast=head;while(fast!=null){ListNode temp=fast.next;fast.next=slow;slow=fast;fast=temp;}return slow;}
}

七、合并k个升序链表

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[1->4->5,1->3->4,2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
思路:

在长度为n的结点数组中,遍历n次,找到最小的结点,然后放到新链表的下一个。并且更新最小结点为最小结点的下一个。

外层循环while(true),在内层循环for(int i=0;i<n;i++)中如果没有找到一个最小的节点(说明已经寻找完毕了,这时就要break;)

代码:
class Solution {public ListNode mergeKLists(ListNode[] lists) {int k=lists.length;ListNode dummyHead=new ListNode();ListNode cur=dummyHead;while(true){ListNode minNode=null;int minPointer=-1;for(int i=0;i<k;i++){if(lists[i]==null)continue;if(minNode==null||lists[i].val<minNode.val){minNode=lists[i];minPointer=i;}}if(minPointer==-1)break;//结束了 链表里面没有东西了cur.next=minNode;cur=cur.next;lists[minPointer]=lists[minPointer].next;}return dummyHead.next;}
}

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

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

相关文章

Spring Boot - 优雅实现支持通配符和IP段的IP访问黑白名单机制

文章目录 CodeIpAccessInterceptoraddInterceptor工具类配置文件 application.yml单元测试 Code 废话不多说&#xff0c;直接上码 IpAccessInterceptor package cn.cloud.bus.module.servicebus.framework.ipconfig;import cn.cloud.bus.module.servicebus.util.IpFilterUti…

深入理解计算机系统 CSAPP 家庭作业11.10

A: //home.html <form action"/cgi-bin/adder" method"GET"><ul><li><label for"n1">n1:</label><input type"text" id"n1" name"n1" /> //name的值决定页面提交后&#xf…

栈知识梳理和函数实现

参考此文章数据结构——栈&#xff0c;此文章写的更详细&#xff0c;由于我们都是学自于比特课程&#xff0c;这里做个自我备份&#xff0c;方便后续查阅、修改和补充。 栈知识梳理和函数实现 前言1.栈是什么&#xff1f;2.栈的接口实现2.1初始化栈2.2入栈2.3 出栈2.4 获取栈顶…

C语言图书信息管理系统

题目&#xff1a;图书信息管理系统 内容及主要功能描述&#xff1a; 该系统用于管理图书信息&#xff0c;包括图书的增加、删除、查找、修改、浏览、按出版社统计图书数量等功能。具体功能包括&#xff1a; 增加图书&#xff1a;输入图书信息并添加到系统中。删除图书&#x…

浅谈WebSerice

一. 什么是WebService Web Service也称为web服务&#xff0c;它是一种跨编程语言和操作系统平台的远程调用技术。Web Service采用标准的SOAP协议传输&#xff08;SOAP&#xff1a;Simple Object Access Protocol简单对象访问协议&#xff0c;soap属于w3c标准。并且soap协议是基…

C++ 算法:从基础到高级

C 算法&#xff1a;从基础到高级 C 是一种功能强大且高效的编程语言&#xff0c;广泛应用于系统编程、游戏开发、嵌入式系统以及高性能计算等领域。算法是程序设计的核心&#xff0c;掌握常用算法是成为优秀 C 程序员的必备技能。本文将介绍一些常用的 C 算法&#xff0c;从基…

【漏洞复现】phpStudy 小皮 Windows面板 存在RCE漏洞

靶场资料后台自行领取【靶场】 image-20240726092307252 PhpStudy小皮面板曝RCE漏洞&#xff0c;本质是存储型XSS引发。攻击者通过登录用户名输入XSS代码&#xff0c;结合后台计划任务功能&#xff0c;实现远程代码执行&#xff0c;严重威胁服务器安全。建议立即更新至安全版…

JAVA SE 类和对象

类和对象 类定义和使用类的定义格式 类的实例化什么是实例化 this 引用this引用的特性 对象的构造及初始化如何初始化对象构造方法概念特性 在这里插入图片描述 **注意**&#xff1a; 封装封装的概念封装扩展之包导入包中的类自定义包包的访问权限控制举例 static成员static修饰…

Spring Cloud全解析:入门指南与概览,轻松掌握微服务架构的基石

springcloud简介 微服务&#xff1f; 微服务是一种架构风格&#xff0c;将单体应用划分为小型的服务单元&#xff0c;微服务之间使用HTTP的API进行资源访问和操作&#xff0c;与SOA不同的是&#xff0c;SOA架构侧重于将每个单体应用的服务集成到ESB(消息总线)上&#xff0c;而…

P1029 [NOIP2001 普及组] 最大公约数和最小公倍数问题

[NOIP2001 普及组] 最大公约数和最小公倍数问题 题目描述 输入两个正整数 x 0 , y 0 x_0, y_0 x0​,y0​&#xff0c;求出满足下列条件的 P , Q P, Q P,Q 的个数&#xff1a; P , Q P,Q P,Q 是正整数。 要求 P , Q P, Q P,Q 以 x 0 x_0 x0​ 为最大公约数&#xff0c;以…

【计算机网络】TCP协议详解

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 文章目录 1、引言2、udp和tcp协议的异同3、tcp服务器3.1、接口认识3.2、服务器设计 4、tcp客户端4.1、客户端设计4.2、说明 5、再研Tcp服务端5.1、多进程版5.2、多线程版 5、守护进程化5.1、什么是守护进程5.2…

古籍双层PDF制作教程:保姆级古籍数字化教程

在智慧古籍数字化项目中&#xff0c;很多图书馆要求将古籍导出为双层PDF&#xff0c;并且确保输出双层PDF底层文本与上层图片偏移量控制在1毫米以内。那么本教程带你使用古籍数字化平台&#xff0c;3分钟把一个古籍书籍转化为双侧PDF。 第1步&#xff1a;上传古籍 点批量上传…

注释和关键字

注释 注释就是对代码的解释说明 单行注释 格式&#xff1a; // 多行注释 格式&#xff1a; /* */ 文档注释 格式&#xff1a; /** */ 关键字

云服务器Ubuntu18.04进行Nginx配置

云服务器镜像版本信息&#xff1a;Ubuntu 18.04 server 64bit&#xff0c;本文记录了在改版本镜像上安装Nginx&#xff0c;并介绍了Nginx配置文件目录&#xff0c;便于后面再次有需求时进行复习。 文章目录 Nginx的安装Nginx配置文件分析 Nginx的安装 1.执行下面命令进行安装…

基于FPGA的数字信号处理导航

之前闲暇的时候也看过一些数字信号处理和调制解调的原理及FPGA实现&#xff0c;不管是DDS、FIR、IIR滤波器&#xff0c;还是ASK、FSK、上变频、下变频的实现&#xff0c;都是比较简单的&#xff08;仅限于实现&#xff0c;不做深入讨论&#xff09;&#xff0c;而这些算法使用F…

玩转CSS:用ul li +JS 模拟select,避坑浏览器不兼容。

玩转CSS&#xff1a;用ul li JS 模拟select&#xff0c;避坑浏览器不兼容。 在前端的工作中&#xff0c;经常会遇到 selcet控件&#xff0c;但我们用css来写它的样式时候&#xff0c;总是不那么令人满意&#xff0c;各种浏览器不兼容啊有没有&#xff1f; 那么&#xff0c;我…

西电网络空间安全综合953考研分享||西安电子科技大学

一、院校选择 如何选择适合自己的学校以及专业 1. 首先要对自己选择的学校有热情&#xff0c;选择自己最想去的学校 2. 其次选择在自己能力范围内努力能考上的学校&#xff0c;综合考虑地区&#xff08;不同地区公共课分数有一定的差别&#xff09;、学校&#xff08;建议跨…

关于MyBatis的缓存详解

MyBatis 是一个流行的 Java 持久层框架&#xff0c;它提供了对数据库的简单操作和映射。MyBatis 的缓存机制是其核心特性之一&#xff0c;它可以帮助开发者提高应用程序的性能&#xff0c;通过减少对数据库的直接访问次数来降低数据库的负载。 1. MyBatis 缓存介绍 默认缓存行…

Vue3计算属性终极实战:可媲美Element Plus Tree组件研发之节点勾选

前面完成了JuanTree组件的节点编辑和保存功能后&#xff0c;我们把精力放到节点勾选功能实现上来。**注意&#xff0c;对于组件的开发者来说&#xff0c;要充分考虑用户的使用场景&#xff0c;组件提供的多个特性同时启用时必须要工作良好。**就拿Tree组件来说&#xff0c;用户…

大模型训练为何离不开GPU?深度解析与显卡推荐

在人工智能的蓬勃发展中&#xff0c;大模型的训练成为了热门话题。然而&#xff0c;许多人还不清楚为什么训练这些庞大的模型需要GPU&#xff08;图形处理单元&#xff09;。本文将深入探讨GPU在大模型训练中的重要性&#xff0c;并推荐几款适合的显卡。 一、GPU与CPU的区别 …