算法学习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…

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

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

JAVA SE 类和对象

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

【计算机网络】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;上传古籍 点批量上传…

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

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

玩转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;建议跨…

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

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

如何保证前后端交互信息不被篡改。

先说说前后端有哪些认证方式来保证&#xff1a; 基于 session 的认证方式&#xff1a;前端在用户登录成功后&#xff0c;后端会在服务器端生成一个唯一的 session ID&#xff0c;并将该 session ID 返回给前端&#xff0c;在后续的请求中&#xff0c;前端需要带上该 session ID…

【CUDA Runtime】第一个“Hello World“程序

文章目录 前言前提须知CUDA Runtime 简介核心功能优势和应用 使用CudaRuntime进行第一个"Hello world"程序创建CudaRuntime工程选择GPU函数原型参数返回值作用 获取支持Cuda的GPU信息获取支持Cuda的GPU数量获取设备属性运行展示 在GPU上分配内存把需要运行的主机内存…

数据库密码实现加盐加密处理

在实际的开发中&#xff0c;我们的数据库密码一般都是明文的方式存储在数据库中&#xff0c;但是&#xff0c;这种操作非常不安全&#xff0c;容易被黑&#xff01; 那么&#xff0c;此时我们就需要对其进行加密处理&#xff0c;市面上比较常见的就是MD5加密了&#xff0c;但是…

【Linux】syscall sys_write流程摸索

这是通过tty进行摸索sys_write的流程。 在前面的博客里&#xff0c;我们可以看到基于内核C语言源代码日志打印&#xff0c;在打印的日志里边包含&#xff1a;日期&#xff0c;时间&#xff0c;当前文件所在代码目录&#xff0c;当前执行函数名&#xff0c;当前文件执行行号&am…

运维团队如何借助分布式部署提升监控效率与可靠性

随着企业IT基础设施的日益复杂和分布式架构的广泛应用&#xff0c;传统的监控解决方案已经难以满足现代运维团队的需求。在这样的背景下&#xff0c;分布式部署作为一种新型的监控架构&#xff0c;以其灵活性、可扩展性和高可用性&#xff0c;成为了运维团队提升监控效率与可靠…

C++模版基础知识与STL基本介绍

目录 一. 泛型编程 二. 函数模板 1. 概念 2. 函数模版格式 3. 函数模版的原理 4. 模版函数的实例化 (1). 隐式实例化 (2.) 显式实例化 5. 模版参数的匹配原则 三. 类模板 1. 类模板的定义格式 2. 类模板的实例化 四. STL的介绍 1. 什么是STL&#xff1f; 2. STL的版…

3.5-RNN文本生成

1语言模型生成文本的顺序 前面我们已经能够实现使用下图的LSTM网络进行语言建模&#xff1b; 对于一个已经在语料库上学习好的LSTM模型&#xff1b;如果语料库就只是you say goobye and i say hello&#xff1b;那么当把单词i输入到模型中&#xff0c;Time xxx层的第一个LSTM…

苍穹外卖01

0. 配置maven (仅一次的操作 1.项目导入idea 2. 保证nginx服务器运行 &#xff08;nginx.exe要在非中文的目录下&#xff09; 开启服务&#xff1a; start nginx 查看任务进程是否存在&#xff1a; tasklist /fi "imagename eq nginx.exe" 关闭ngi…