【LeetCode-面试经典150题-day14】

 

目录

19.删除链表的倒数第N个结点

 82.删除排序链表中的重复元素Ⅱ

 61. 旋转链表

 86.分隔链表

 146.LRU缓存


19.删除链表的倒数第N个结点

题意:

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

【输入样例】head = [1,2,3,4,5],n=2

【输出样例】[1,2,3,5]

解题思路:

1. 双指针p和q,初始哈指向头节点;

2. 移动q,直到p和q之间相隔的元素为n

3. 同时移动p和q,直到q指向链表结尾的null

4. p.next = p.next.next

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dummyHead = new ListNode(0,head);ListNode p = dummyHead;ListNode q = head;for(int i=0; i< n; i++){q = q.next;}while(q != null){q = q.next;p = p.next;}p.next = p.next.next;ListNode ans = dummyHead.next;return ans;}
}

时间: 击败了100.00%

内存: 击败了64.22%

 82.删除排序链表中的重复元素Ⅱ

题意:

给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。

【输入样例】head = [1,1,1,2,3]

【输出样例】[2,3]

解题思路:

1. 定义一个哑节点,指向链表的头节点

2. 指针cur指向哑节点,遍历链表

3. 如果cur.next.val == cur.next.next.val,将cur.next以及后面拥有相同元素x(x=cur.next.val)的节点全部删除;

4. 不断移除重复元素,直到cur.next是空节点或元素值不等于x

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode deleteDuplicates(ListNode head) {if(head == null){return head;}ListNode dummy = new ListNode(0,head);ListNode cur = dummy;while(cur.next != null && cur.next.next != null){if(cur.next.val == cur.next.next.val){int x = cur.next.val;while(cur.next != null && cur.next.val == x){cur.next = cur.next.next;//不断跳过重复值的数}}else{cur = cur.next;//继续往下遍历}}return dummy.next;//指向head}
}

时间: 击败了100.00%

内存: 击败了86.54%

 61. 旋转链表

题意:

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

【输入样例】head = [1,2,3,4,5],k=2

【输出样例】[4,5,1,2,3]

解题思路:

1. 定义一个哑节点,指向链表的头节点

2. 遍历链表,统计链表的长度,优化移动次数为k%n;

3. 将原始链表形成闭环,并计算count = n-k%n,表示从当前节点开始遍历count次,可以找到尾节点;

4. 不断移动指针,直到count = 0,此时定义一个新节点,指向dummy.next,作为新链表的头节点,dummy.next赋值null实现断链

 

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode rotateRight(ListNode head, int k) {if(k == 0 || head==null || head.next == null){return head;}//一次遍历,统计链表的长度n,移动k次相当于移动k%n次;int n = 1;ListNode dummy = head;while(dummy.next !=null){dummy = dummy.next;++n;}int count = n - k % n;if(count == n){return head;}dummy.next = head;//形成闭环while(count-- > 0){dummy = dummy.next;}ListNode result = dummy.next;dummy.next = null;return result;}
}

时间: 击败了100.00%

内存: 击败了68.97%

 86.分隔链表

题意:

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你应当 保留 两个分区中每个节点的初始相对位置。

【输入样例】head = [1,4,3,2,5,2],x=3

【输出样例】[1,2,2,4,3,5]

解题思路:

1.借助两个链表,一个存储小于x的节点,一个存储大于等于x的节点,之后将两个链表进行拼接即可。

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode partition(ListNode head, int x) {ListNode minNext = new ListNode(0);ListNode minhead = minNext;ListNode maxNext = new ListNode(0);ListNode maxhead = maxNext;while(head!=null){if(head.val < x){minNext.next = head;minNext = minNext.next;}else{maxNext.next = head;maxNext = maxNext.next;}head = head.next;}maxNext.next = null;minNext.next = maxhead.next;return minhead.next;}
}

时间: 击败了100.00%

内存: 击败了20.49%

 146.LRU缓存

题意:

请你设计并实现一个满足  LRU (最近最少使用) 缓存 约束的数据结构。

实现 LRUCache 类:

  • LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

【输入样例】

["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]

【输出样例】

[null, null, null, 1, null, -1, null, -1, 3, 4]
解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1);    // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2);    // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1);    // 返回 -1 (未找到)
lRUCache.get(3);    // 返回 3
lRUCache.get(4);    // 返回 4

解题思路:哈希表+双向链表

1. 双向链表按照被使用的顺序存储键值对,最靠近头部的键值对是最近使用的,最靠近尾部的键值对是最久未使用的。

2. 哈希表缓存数据的键,映射到其在双向链表中的位置

3. 使用哈希表进行定位,找出缓存项在双向链表中的位置,并将其移动到双向链表的头部,如果key不存着哈希表中,则返回-1或者在链表的头部新建一个节点。

public class LRUCache {private Map<Integer,DLinkedNode> cache = new HashMap<Integer,DLinkedNode>();private int size;private int capacity;private DLinkedNode head,tail;public LRUCache(int capacity) {this.size = 0;this.capacity = capacity;head = new DLinkedNode();tail = new DLinkedNode();head.next = tail;tail.prev = head;}public int get(int key) {DLinkedNode node = cache.get(key);if(node == null){//链表中不存在此值return -1;}//存在,将其移动到双向链表的头部moveToHead(node);return node.value;}public void put(int key, int value) {DLinkedNode node = cache.get(key);if(node == null){//如果key不存着,要创建一个新节点//需要判断插入之后长度是否会超过容量DLinkedNode newNode = new DLinkedNode(key,value);cache.put(key,newNode);addToHead(newNode);++size;//每加进来一个元素,size++if(size > capacity){//删除尾部节点和哈希表中的对应项DLinkedNode tail = removeTail();cache.remove(tail.key);--size;}}else{//key存在,哈希表定位,修改value,移到头部node.value = value;moveToHead(node);}}private void addToHead(DLinkedNode node){//添加到双向链表头部node.prev = head;node.next = head.next;head.next.prev = node;head.next = node;}private void removeNode(DLinkedNode node){//从当前位置移走node.prev.next = node.next;node.next.prev = node.prev;}private void moveToHead(DLinkedNode node){removeNode(node);addToHead(node);}private DLinkedNode removeTail(){DLinkedNode node = tail.prev;removeNode(node);return node;}
}class DLinkedNode{int key;int value;DLinkedNode prev;DLinkedNode next;public DLinkedNode(){}public DLinkedNode(int key, int value){this.key = key;this.value = value;}
}
/*** Your LRUCache object will be instantiated and called as such:* LRUCache obj = new LRUCache(capacity);* int param_1 = obj.get(key);* obj.put(key,value);*/

时间: 击败了23.27%

内存: 击败了97.38%

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

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

相关文章

大数据之linux入门

一、linux是什么 linux操作系统 开发者是林纳斯-托瓦兹&#xff0c;出于个人爱好编写。linux是一个基于posix和unix的多用户、多任务、支持多线程和多CPU的操作系统。 Unix是20世纪70年代初出现的一个操作系统&#xff0c;除了作为网络操作系统之外&#xff0c;还可以作为单…

论文阅读_扩散模型_LDM

英文名称: High-Resolution Image Synthesis with Latent Diffusion Models 中文名称: 使用潜空间扩散模型合成高分辨率图像 地址: https://ieeexplore.ieee.org/document/9878449/ 代码: https://github.com/CompVis/latent-diffusion 作者&#xff1a;Robin Rombach 日期: 20…

基于ADAU1452 DSP ANC和AEC算法的实现

是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?加我微信hezkz17, 本群提供音频技术答疑服务,+群附加赠送,DSP音频项目核心开发资料, 1 使用Sigma中的NLMS算法模块 对应C源代码:

Web开发模式、API接口、restful规范、序列化和反序列化、drf安装和快速使用、路由转换器(复习)

一 Web开发模式 1. 前后端混合开发模式 前后端混合开发模式是一种开发方式&#xff0c;将前端和后端的开发工作结合在一起&#xff0c;以加快项目的开发速度和 提高协作效率。这种模式通常用于快速原型开发、小型项目或敏捷开发中。在前后端混合开发模式中&#xff0c;前端和…

Rust之自动化测试(一):如何编写测试

开发环境 Windows 10Rust 1.71.1 VS Code 1.81.1 项目工程 这里继续沿用上次工程rust-demo 编写自动化测试 Edsger W. Dijkstra在他1972年的文章《谦逊的程序员》中说&#xff0c;“程序测试可以是一种非常有效的方法来显示错误的存在&#xff0c;但它对于显示它们的不存在…

视频分割合并工具说明

使用说明书&#xff1a;视频分割合并工具 欢迎使用视频生成工具&#xff01;本工具旨在帮助您将视频文件按照指定的规则分割并合并&#xff0c;以生成您所需的视频。 本程序还自带提高分辨率1920:1080&#xff0c;以及增加10db声音的功能 软件下载地址 https://github.com/c…

Fei-Fei Li-Lecture 16:3D Vision 【斯坦福大学李飞飞CV课程第16讲:3D Vision】

目录 P1 2D Detection and Segmentation P2 Video 2D time series P3 Focus on Two Problems P4 Many more topics in 3D Vision P5-10 Multi-View CNN P11 Experiments – Classification & Retrieval P12 3D Shape Representations P13--17 3D Shape Represen…

echarts 甘特图一组显示多组数据

<template><el-button type"primary" click"addlin">添加线</el-button><el-button type"success" click"addArea">添加区域</el-button><div ref"echart" id"echart" class&qu…

应急物资管理系统|智物资DW-S300提升应急响应能力

项目背景 智慧应急物资管理系统&#xff08;智装备DW-S300&#xff09;是一套成熟系统&#xff0c;依托互3D技术、云计算、大数据、RFID技术、数据库技术、AI、视频分析技术对RFID智能仓库进行统一管理、分析的信息化、智能化、规范化的系统。 本项目采用东识智慧应急物资管理…

(三)行为模式:6、备忘录模式(Memento Pattern)(C++示例)

目录 1、备忘录模式&#xff08;Memento Pattern&#xff09;含义 2、备忘录模式的UML图学习 3、备忘录模式的应用场景 4、备忘录模式的优缺点 &#xff08;1&#xff09;优点&#xff1a; &#xff08;2&#xff09;缺点 5、C实现备忘录模式的实例 1、备忘录模式&#…

javaee spring 自动注入,如果满足条件的类有多个如何区别

如图IDrinkDao有两个实现类 方法一 方法二 Resource(name“对象名”) Resource(name"oracleDrinkDao") private IDrinkDao drinkDao;

C# task多线程创建,暂停,继续,结束使用

1、多线程任务创建 private void button1_Click(object sender, EventArgs e) //创建线程{CancellationToken cancellationToken tokensource.Token;Task.Run(() > //模拟耗时任务{for (int i 0; i < 100; i){if (cancellationToken.IsCancellationRequested){return;…