【算法练习】leetcode链表算法题合集

在这里插入图片描述

链表总结

  1. 增加表头元素
  2. 倒数节点,使用快慢指针
  3. 环形链表(快慢指针)
  4. 合并有序链表,归并排序
  5. LRU缓存

算法题

删除链表元素

删除链表中的节点

LeetCode237. 删除链表中的节点

复制后一个节点的值,删除后面的节点(1->5->3->4,删除5的话,先调整为1->3->3->4,再删除第二个3的节点)

class Solution {public void deleteNode(ListNode node) {node.val = node.next.val;node.next = node.next.next;}
}
删除链表的倒数第 N 个结点

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

快慢节点,使用虚拟节点,删除节点

当fast的next节点到了链表外,slow的next节点是第n个节点。找到slow的next节点,删除。

class Solution_LC19 {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dummy = new ListNode(-1);dummy.next = head;ListNode slow = dummy;ListNode fast = dummy;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 dummy.next;}}
删除排序链表中的重复元素

LeetCode83 删除排序链表中的重复元素

和当前节点比较值,相同则删掉,不同则下一个节点

class Solution_LC83 {public ListNode deleteDuplicates(ListNode head) {ListNode cur = head;while (cur != null) {int val = cur.val;if (cur.next != null && cur.next.val == val) {cur.next = cur.next.next;} else {cur = cur.next;}}return head;}
}
删除排序链表中的重复元素 II(**)

LeetCode82. 删除排序链表中的重复元素 II

定义两个节点。cur节点是用来比较的节点,pre节点是用来删除的。找到cur节点,该节点和next节点不一致,pre.next=cur,等于是删除了pre和cur之间的元素。

class Solution {public ListNode deleteDuplicates(ListNode head) {ListNode dummy = new ListNode(-1);dummy.next = head;ListNode pre = dummy;ListNode cur = head;while (cur != null && cur.next != null) {int x = cur.val;if (cur.next.val == x) {while (cur != null && cur.val == x) {cur = cur.next;}pre.next = cur;} else {cur = cur.next;pre = pre.next;}}return dummy.next;}
}

旋转链表

反转链表

LeetCode206. 反转链表

头插法。pre和cur不断向后移动,直到cur为空,pre为最后一个节点(遍历顺序的最后一个)。

class Solution {public ListNode reverseList(ListNode head) {ListNode pre = null;ListNode cur = head;while (cur != null) {ListNode next = cur.next;cur.next = pre;pre = cur;cur = next;}return pre;}
}
K 个一组翻转链表

LeetCode25. K 个一组翻转链表

  • 获取k个节点一组的链表

  • 翻转链表

  • pre的后面一个节点是start,end的最后一个节点是next。

class Solution {public ListNode reverseKGroup(ListNode head, int k) {ListNode dummy = new ListNode(-1);dummy.next = head;ListNode pre = dummy;ListNode end = dummy;while (end.next != null) {for (int i = 0; i < k&&end!=null; i++) {end = end.next;}if (end == null) {break;}ListNode next = end.next;ListNode start = pre.next;end.next = null;pre.next = reverse(start);start.next = next;pre = start;end = start;}return dummy.next;}private ListNode reverse(ListNode head) {ListNode pre = null;ListNode cur = head;while (cur != null) {ListNode next = cur.next;cur.next = pre;pre = cur;cur = next;}return pre;}
}
LeetCode61. 旋转链表

LeetCode61. 旋转链表.

  • 获取链表的尾结点

  • 尾结点连接头节点

  • 找到切割点(切割点的前一个节点)

  • 切割。获取next节点,将当前节点的next置为空,切断。

class Solution {public ListNode rotateRight(ListNode head, int k) {if (k == 0 || head == null || head.next == null) {return head;}ListNode cur = head;int n = 1;while (cur.next != null) {cur = cur.next;n++;}int add = n - k % n;if (add == n) {return head;}cur.next = head;while (add > 0) {cur = cur.next;add--;}ListNode next = cur.next;cur.next = null;return next;}
}

交换链表节点

LeetCode24. 两两交换链表中的节点(⭐️高频)

LeetCode24. 两两交换链表中的节点

定义虚拟头结点

获取可以交换的节点,进行节点操作

将node1节点置为前置结点,进行下一轮操作

class Solution {public ListNode swapPairs(ListNode head) {ListNode dummy = new ListNode(-1, head);ListNode cur = dummy;while (cur.next != null && cur.next.next != null) {ListNode node1 = cur.next;ListNode node2 = node1.next;ListNode next = node2.next;cur.next = node2;node2.next = node1;node1.next = next;cur = node1;}return dummy.next;}
}

环形/相交/回文链表

LeetCode141. 环形链表(腾讯)

LeetCode141. 环形链表(腾讯)

使用快慢指针,如果快指针最后到达慢指针,则存在环。

public class Solution {public boolean hasCycle(ListNode head) {ListNode fast = head;ListNode slow = head;while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;if (fast == slow) {return true;}}return false;}
}
LeetCode142. 环形链表II

LeetCode142. 环形链表II.

快慢指针

a+b+n(b+c)=2(a+b) --> a=(n-1)(b+c)+c

public class Solution {public ListNode detectCycle(ListNode head) {ListNode fast = head;ListNode slow = head;while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;if (slow == fast) {ListNode node1 = head;ListNode node2 = fast;while (node1 != node2) {node1 = node1.next;node2 = node2.next;}return node1;}}return null;}
}
LeetCode160.相交链表

160. 相交链表

要进行临界值判断

相交的链表后面一段是公共的,a+b+c=c+b+a。

public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {if (headA == null || headB == null) {return null;}ListNode p1 = headA;ListNode p2 = headB;while (p1 != p2) {p1 = p1 == null ? headB : p1.next;p2 = p2 == null ? headA : p2.next;}return p1;}
}
LeetCode234. 回文链表

234. 回文链表

寻找中间节点,并反转前面列表

pre是反转链表的头结点,slow是后面链表的头结点。比较节点的值,判断是否回文

class Solution {public boolean isPalindrome(ListNode head) {//1-2-3-2-1ListNode fast = head;ListNode slow = head;ListNode pre = null;while (fast != null && fast.next != null) {fast = fast.next.next;ListNode next = slow.next;slow.next = pre;pre = slow;slow = next;}if (fast != null) {slow = slow.next;}while (pre != null && slow != null) {if (slow.val != pre.val) {return false;} else {slow = slow.next;pre = pre.next;}}return true;}
}

链表合并

LeetCode2: 两数相加

LeetCode2: 两数相加

对应数位的值相加,计算当前节点以及向上的值。

class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {ListNode dummy = new ListNode(-1);ListNode cur = dummy;int carry = 0;while (l1 != null || l2 != null || carry != 0) {int sum = (l1 == null ? 0 : l1.val) + (l2 == null ? 0 : l2.val) + carry;carry = sum / 10;ListNode tmp = new ListNode(sum % 10);cur.next = tmp;cur = tmp;l1 = l1 == null ? null : l1.next;l2 = l2 == null ? null : l2.next;}return dummy.next;}
}
LeetCode445: 两数相加II

LeetCode445: 两数相加II

使用堆栈,用于顺序相反获取值

链表的拼接和上一题不同。上一题是不断往链表后面添加元素;这一题是不断往前面添加元素。

class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {Stack<Integer> stack1 = new Stack<>();Stack<Integer> stack2 = new Stack<>();while (l1 != null) {stack1.push(l1.val);l1 = l1.next;}while (l2 != null) {stack2.push(l2.val);l2 = l2.next;}int carry = 0;ListNode cur = null;while (!stack1.isEmpty() || !stack2.isEmpty() || carry != 0) {int sum = (stack1.isEmpty() ? 0 : stack1.pop()) + (stack2.isEmpty() ? 0 : stack2.pop()) + carry;carry = sum / 10;ListNode tmp = new ListNode(sum % 10);tmp.next = cur;cur = tmp;}return cur;}
}
LeetCode21: 合并两个有序链表

21. 合并两个有序链表

挨个遍历比较大小,是最容易想到的方案

使用递归。当l1.val < l2.vall1.next = mergeTwoLists(l1.next, l2);

class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {ListNode dummy = new ListNode(-1);ListNode cur = dummy;while (list1 != null && list2 != null) {if (list1.val < list2.val) {cur.next = new ListNode(list1.val);cur = cur.next;list1 = list1.next;} else {cur.next = new ListNode(list2.val);cur = cur.next;list2 = list2.next;}}if (list1 != null) {cur.next = list1;} else {cur.next = list2;}return dummy.next;}
}
LeetCode23: 合并K个排序链表

23. 合并 K 个升序链表

挨个遍历处理

class Solution {public ListNode mergeKLists(ListNode[] lists) {ListNode ans = null;for (int i = 0; i < lists.length; i++) {ans =mergeTwoLists(ans, lists[i]);}return ans;}public ListNode mergeTwoLists(ListNode list1, ListNode list2) {if (list1 == null || list2 == null) {return list1 == null ? list2 : list1;}ListNode dummy = new ListNode(-1);ListNode cur = dummy;while (list1 != null && list2 != null) {if (list1.val < list2.val) {cur.next = new ListNode(list1.val);cur = cur.next;list1 = list1.next;} else {cur.next = new ListNode(list2.val);cur = cur.next;list2 = list2.next;}}if (list1 != null) {cur.next = list1;} else {cur.next = list2;}return dummy.next;}
}

分治合并,将链表数组拆分成2段,处理好后合并。

class Solution {public ListNode mergeKLists(ListNode[] lists) {return merge(lists, 0, lists.length - 1);}private ListNode merge(ListNode[] lists, int l, int r) {if (l == r) {return lists[l];}if (l > r) {return null;}int mid = (l + r) / 2;return mergeTwoLists(merge(lists, l, mid), merge(lists, mid + 1, r));}public ListNode mergeTwoLists(ListNode list1, ListNode list2) {if (list1 == null || list2 == null) {return list1 == null ? list2 : list1;}ListNode dummy = new ListNode(-1);ListNode cur = dummy;while (list1 != null && list2 != null) {if (list1.val < list2.val) {cur.next = new ListNode(list1.val);cur = cur.next;list1 = list1.next;} else {cur.next = new ListNode(list2.val);cur = cur.next;list2 = list2.next;}}if (list1 != null) {cur.next = list1;} else {cur.next = list2;}return dummy.next;}
}

使用优先队列

class Solution {public ListNode mergeKLists(ListNode[] lists) {//优先队列默认是小顶堆,最小的元素放在队头,即a-bPriorityQueue<ListNode> priorityQueue = new PriorityQueue<ListNode>((a, b) -> {return a.val - b.val;});for (int i = 0; i < lists.length; i++) {if(lists[i]!=null){
priorityQueue.add(lists[i]);}}ListNode dummy = new ListNode(-1);ListNode cur = dummy;while (!priorityQueue.isEmpty()) {ListNode listNode = priorityQueue.poll();ListNode next = listNode.next;cur.next = listNode;cur = listNode;if (next != null) {priorityQueue.add(next);}}return dummy.next;}
}
LeetCode148: 排序链表

148. 排序链表

使用优先队列,最简单。

使用归并排序。做链表拆分。

可以和回文链表做比较,必须熟悉掌握两个链表合并的逻辑。

class Solution {public ListNode sortList(ListNode head) {if (head == null || head.next == null) {return head;}ListNode fast = head.next;ListNode slow = head;while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;}ListNode next = slow.next;slow.next = null;ListNode listNode1 = sortList(head);ListNode listNode2 = sortList(next);ListNode dummy = new ListNode(-1);ListNode cur =dummy;while (listNode1 != null && listNode2 != null) {if (listNode1.val < listNode2.val) {cur.next = listNode1;cur = cur.next;listNode1 = listNode1.next;} else {cur.next = listNode2;cur = cur.next;listNode2 = listNode2.next;}}cur.next = listNode1 == null ? listNode2 : listNode1;return dummy.next;}
}

LRU缓存

LeetCode146. LRU 缓存

146. LRU 缓存

使用LinkedHashMap,设置accessOrder为true,最近访问的元素会排在最后。而removeEldestEntry当条件满足的时候会移除最老的元素。

class LRUCache extends LinkedHashMap<Integer, Integer> {private int capacity;public LRUCache(int capacity) {super(capacity, 0.75f, true);this.capacity = capacity;}public int get(int key) {return super.getOrDefault(key, -1);}public void put(int key, int value) {super.put(key, value);}protected boolean removeEldestEntry(Map.Entry<Integer, Integer> entry) {return size() > this.capacity;}
}

使用Hash表和双向链表

双向链表记录访问顺序,Hash表获取元素

获取元素,将元素放在最前(移除当前元素在双向链表中的原位置,放在前面)。

存放元素,如果元素已存在,进行更新值,且将元素放在最前;如果元素不存在,添加元素要判断边界,超过边界要移除最早访问的元素(从链表和Hash表中移除)。

class LRUCache extends LinkedHashMap<Integer, Integer> {public class DLinkedNode {int key;int val;DLinkedNode prev;DLinkedNode next;public DLinkedNode() {}public DLinkedNode(int key, int val) {this.key = key;this.val = val;}}private Map<Integer, DLinkedNode> map = new HashMap<>();private int size;private int capacity;private DLinkedNode head, tail;public LRUCache(int capacity) {this.capacity = capacity;size = 0;head = new DLinkedNode();tail = new DLinkedNode();head.next = tail;tail.prev = head;}public int get(int key) {DLinkedNode dLinkedNode = map.get(key);if (dLinkedNode == null) {return -1;} else {moveToHead(dLinkedNode);return dLinkedNode.val;}}private void moveToHead(DLinkedNode node) {removeNode(node);addToHead(node);}private void addToHead(DLinkedNode node) {DLinkedNode next = head.next;head.next = node;node.prev = head;node.next = next;next.prev = node;}private void removeNode(DLinkedNode node) {DLinkedNode prev = node.prev;DLinkedNode next = node.next;prev.next = next;next.prev = prev;}private DLinkedNode removeTail() {DLinkedNode prev = tail.prev;removeNode(prev);return prev;}public void put(int key, int value) {DLinkedNode node = map.get(key);if (node == null) {DLinkedNode newNode = new DLinkedNode(key, value);map.put(key, newNode);addToHead(newNode);size++;if (size > capacity) {DLinkedNode tail = removeTail();map.remove(tail.key);size--;}} else {node.val = value;moveToHead(node);}}
}

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

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

相关文章

java球队信息管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web球队信息管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5…

深度学习之RNN

1.循环神经网络 在时间t的时候&#xff0c;对于单个神经元来讲它的输出y(t)如下 wx是对于输入x的权重&#xff0c;wy是对于上一时刻输出的权重 所以循环神经网络有两个权重。 如果有很多这样的神经元并排在一起 则在t时刻的输出y为 这时输入输出都是向量 2.记忆单元 由于循…

车队试验的远程实时显示方案

风丘科技推出的数据远程实时显示方案更好地满足了客户对于试验车队远程实时监控的需求&#xff0c;并真正实现了试验车队的远程管理。随着新的数据记录仪软件IPEmotion RT和相应的跨平台显示解决方案的引入&#xff0c;让我们的客户端不仅可在线访问记录器系统状态&#xff0c;…

git unable to create temporary file: No space left on device(git报错)

1.问题 1.1 vscode中npm run serve跑项目的时候&#xff0c;进度达到95%的时候一直卡着无进度&#xff1b; 1.2 git命令提交代码报错&#xff1b; 2.具体解决 这个错误通常表示你的磁盘空间已经满了&#xff0c;导致 Git 无法在临时目录中创建文件。2.1 清理磁盘空间&#xf…

低代码平台在金融银行中的应用场景

随着数字化转型的推进&#xff0c;商业银行越来越重视技术在业务发展中的作用。在这个背景下&#xff0c;白码低代码平台作为一种新型的开发方式&#xff0c;正逐渐受到广大商业银行的关注和应用。白码低代码平台能够快速构建各类应用程序&#xff0c;提高开发效率&#xff0c;…

跨境电商引流真的很难吗?了解一下这些技巧!

随着全球电商市场的不断扩大&#xff0c;越来越多的企业开始涉足跨境电商领域&#xff0c;然而&#xff0c;与国内电商相比&#xff0c;跨境电商面临着诸多挑战&#xff0c;其中最大的难题之一就是如何有效地吸引潜在客户。 很多卖家觉得跨境电商引流非常困难&#xff0c;但实…

springBoot整合redis做缓存

一、Redis介绍 Redis是当前比较热门的NOSQL系统之一&#xff0c;它是一个开源的使用ANSI c语言编写的key-value存储系统&#xff08;区别于MySQL的二维表格的形式存储。&#xff09;。和Memcache类似&#xff0c;但很大程度补偿了Memcache的不足。和Memcache一样&#xff0c;R…

BAT log-yyyy-mm-dd.log

日志文件 文件名 日期格式化 https://download.csdn.net/download/spencer_tseng/88673832 https://download.csdn.net/download/spencer_tseng/88673716

探究Android DreamService的梦幻世界

探究Android DreamService的梦幻世界 引言 DreamService的概述 在Android开发中&#xff0c;DreamService是一种特殊类型的服务&#xff0c;它可以用于创建梦幻世界的屏保应用。梦幻世界是一种用户界面显示模式&#xff0c;当设备进入空闲状态时&#xff0c;系统会自动启动D…

main函数的参数ac和av

概要&#xff1a; main函数有两个参数&#xff0c;ac和av ac表示参数的个数&#xff0c;程序名包括在内。也就是说程序无参数运行时&#xff0c;ac的值为1 av是一个字符串数组&#xff0c;这个数组中的每个元素表示一个参数&#xff0c;程序名包括在内。也就是说&#xff0c…

linux如何清理磁盘,使得数据难以恢复

sda 是硬盘&#xff0c;sda1 和 sda2 是硬盘的两个分区。centos-root 是一个逻辑卷&#xff0c;挂载在根目录 /。 /dev/sda 是硬盘&#xff0c;/dev/sda1 和 /dev/sda2 是硬盘的两个分区。 [rootnode2 ~]# dd if/dev/urandom of/dev/sda bs4M这个命令将从 /dev/urandom 读取随…

【JavaScript】垃圾回收与内存泄漏

✨ 专栏介绍 在现代Web开发中&#xff0c;JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性&#xff0c;还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言&#xff0c;JavaScript具有广泛的应用场景&#x…

JAVA语言—AOP基础

1、AOP概述 AOP&#xff1a;AOP&#xff08;Aspect Oriented Programming&#xff09;&#xff0c;即面向切面编程&#xff0c;可以说是OOP&#xff08;Object Oriented Programming&#xff0c;面向对象编程&#xff09;的补充和完善。 场景&#xff1a;案例部分功能运行较慢&…

「微服务」微服务架构中的数据一致性

在微服务中&#xff0c;一个逻辑上原子操作可以经常跨越多个微服务。即使是单片系统也可能使用多个数据库或消息传递解决方案。使用多个独立的数据存储解决方案&#xff0c;如果其中一个分布式流程参与者出现故障&#xff0c;我们就会面临数据不一致的风险 - 例如在未下订单的情…

Java版商城:Spring Cloud+SpringBoot b2b2c电子商务平台,多商家入驻、直播带货及免 费 小程序商城搭建

随着互联网的快速发展&#xff0c;越来越多的企业开始注重数字化转型&#xff0c;以提升自身的竞争力和运营效率。在这个背景下&#xff0c;鸿鹄云商SAAS云产品应运而生&#xff0c;为企业提供了一种简单、高效、安全的数字化解决方案。 鸿鹄云商SAAS云产品是一种基于云计算的软…

[玩转AIGC]LLaMA2训练自己的中文故事撰写神器(content generation)

目录 一、下载并加载中文数据集二、中文数据集处理1、数据格式2、数据集处理之tokenizer训练格式1&#xff09;先将一篇篇文本拼凑到一起&#xff08;只是简单的拼凑一起&#xff0c;用于训练tokenizer&#xff09;2&#xff09;将数据集进行合并 3、数据集处理之模型&#xff…

Ruff物联网数采网关助力工业企业数字化转型,降本增效

如今&#xff0c;随着工厂数字化转型进程的加速&#xff0c;越来越多的企业对于设备数据感知层及传输层的应用越来越重视&#xff0c;因此工业数采网关也走进了很多人的视野&#xff0c;在工厂数字化转型中扮演着关键角色。 物联网数据采集网关能将各种传感器、执行器等设备连…

sqlilabs第三十二三十三关

Less-32&#xff08;GET - Bypass custom filter adding slashes to dangerous chars) 手工注入 由 宽字符注入可知payload 成功触发报错 http://192.168.21.149/Less-32/ ?id1%df 要写字符串的话直接吧字符串变成ascii码 注意16进制的表示方式 自动注入 sqlmap -u http:…

MySQL常用命令合集(Mac版)

mysql信息 MySQL位置 which mysql查看版本 mysql --version启动与关闭 使用mysql.server启用脚本来执行&#xff0c;默认在/usr/local/mysql/support-files这个目录中。 启动 sudo /usr/local/mysql/support-files/mysql.server start关闭 sudo /usr/local/mysql/suppor…

2023年度业务风险报告:四个新风险趋势

目录 倒票的黄牛愈加疯狂 暴增的恶意网络爬虫 愈加猖獗的羊毛党 层出不穷的新风险 业务风险呈现四个趋势 防御云业务安全情报中心“2023年业务风险数据”统计显示&#xff0c;恶意爬虫风险最多&#xff0c;占总数的37.8%&#xff1b;其次是虚假账号注册&#xff0c;占18.79%&am…