news 2026/10/15 13:27:17

hot100链表

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
hot100链表

基于合并有序链表思路三个题

21. 合并两个有序链表 - 力扣(LeetCode)

虚拟头节点起始,dh指向虚拟头,用尾插法插入较小节点,最后补上剩余的链表,因为链表有序。

class Solution { public ListNode mergeTwoLists(ListNode list1, ListNode list2) { ListNode head = new ListNode(0); ListNode dh = head; while(list1 != null && list2 != null){ if(list1.val <= list2.val){ dh.next = list1; list1 = list1.next; }else{ dh.next = list2; list2 = list2.next; } dh = dh.next; } if(list1 != null){ dh.next = list1; }else{ dh.next=list2; } return head.next; } }

148. 排序链表 - 力扣(LeetCode)

基于递归归并排序把中点两侧排序,然后基于合并有序链表的思路合并,空间复杂度为logn,时间为nlogn。

找中点:注意fast要在slow后面,保证偶数个时候不会无限循环

/** * 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 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 left=head; ListNode right = slow.next; slow.next=null; ListNode leftSort= sortList(head); ListNode rightSort = sortList(right); return mergeTwoLists(leftSort,rightSort); } public ListNode mergeTwoLists(ListNode list1, ListNode list2) { ListNode head = new ListNode(0); ListNode dh = head; while(list1 != null && list2 != null){ if(list1.val <= list2.val){ dh.next = list1; list1 = list1.next; }else{ dh.next = list2; list2 = list2.next; } dh = dh.next; } if(list1 != null){ dh.next = list1; }else{ dh.next=list2; } return head.next; } }

23. 合并 K 个升序链表 - 力扣(LeetCode)

基于归并排序和有序链表合并的思路,递归处理每个链表

注意递归的终止条件和判空。

class Solution { public ListNode mergeKLists(ListNode[] lists) { if(lists.length==0||lists==null)return null; return sortList(lists, 0, lists.length-1); } public ListNode sortList(ListNode[] lists, int left, int right){ if(left==right) return lists[left]; int mid = (right+left)/2; ListNode leftNode = sortList(lists, left, mid); ListNode rightNode = sortList(lists, mid+1, right); return mergeTwoLists(leftNode, rightNode); } public ListNode mergeTwoLists(ListNode list1, ListNode list2) { ListNode head = new ListNode(0); ListNode dh = head; while(list1 != null && list2 != null){ if(list1.val <= list2.val){ dh.next = list1; list1 = list1.next; }else{ dh.next = list2; list2 = list2.next; } dh = dh.next; } if(list1 != null){ dh.next = list1; }else{ dh.next=list2; } return head.next; } }

反转链表系列:

206. 反转链表 - 力扣(LeetCode)

25. K 个一组翻转链表 - 力扣(LeetCode)

定义反转链表的普通方法

  • prev:已经处理好的链表的尾节点。初始指向dummy。

  • cur:从prev出发,向后走 k 步,到达当前待处理组的第 k 个节点(即这一组的尾部)。

  • nextStart:cur.next,即剩余未处理链表的头部(下一组的起点

  • groupHead代表当前待处理链表的头部,fanzhuanRes反转后的新头,

  • 注意反转之后的重新连接。

  • 剩余不足 k 个的节点不需要反转,也不需要额外处理,这部分剩余节点已经通过前一组的尾节点连接到了结果链表中,并且保持了原有的顺序

class Solution { public ListNode reverseKGroup(ListNode head, int k) { ListNode dim = new ListNode(-1); dim.next = head; ListNode prev = dim; while(true){ ListNode cur = prev; for(int i = 0; i <k && cur !=null;i++){ cur = cur.next; } if(cur==null) break; ListNode nextStart = cur.next; cur.next=null; ListNode groupHead = prev.next; ListNode fanzhuanRes= fanzhuan(groupHead); prev.next = fanzhuanRes; prev = groupHead; groupHead.next = nextStart; } return dim.next; } ListNode fanzhuan(ListNode node){ ListNode prev = null; ListNode cur = node;; while(cur != null){ ListNode next = cur.next; cur.next = prev; prev = cur; cur = next; } return prev; } }

环形链表:

141. 环形链表 - 力扣(LeetCode)

快慢指针都在head,注意快指针的终止条件

public class Solution { public boolean hasCycle(ListNode head) { if(head==null || head.next==null)return false; ListNode fast = head; ListNode slow = head; while(fast != null && fast.next != null){ fast=fast.next.next; slow=slow.next; if(slow==fast) return true; } return false; } }

142. 环形链表 II - 力扣(LeetCode)

head ──a──> 入口 ──b──> 相遇点 ↑ │ └──── c ─────┘

slow:a+b

fast:a+b+n(b+c)

a+b+n(b+c) = 2 (a+b)

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

注意点:无环的时候判断fast为空或者next为空都返回空

最后找入口点的时候,代码中不显式写圈数,靠 slow交点位置在环上自然行走来“绕圈”。

public class Solution { public ListNode detectCycle(ListNode head) { if(head==null || head.next==null)return null; ListNode fast=head; ListNode slow=head; while(fast!=null&&fast.next!=null){ fast=fast.next.next; slow=slow.next; if(slow==fast) break; } if(fast==null || fast.next==null) return null; while(head!=slow){ head=head.next; slow=slow.next; } return slow; } }

普通链表题:

146. LRU 缓存 - 力扣(LeetCode)

哈希表:存储key+节点地址

双向链表:包含头尾指针,便于增加和删除,找到前驱后继

哈希的value组成双链表,定义头部为最近使用,尾部为最近不使用

注意两个错误:

get之后要把当前节点删除,搬到头节点后

put覆盖之后要把当前节点删除,搬到头节点后。

class LRUCache { class Node { int key,val; Node prev, next; Node(int key, int val){ this.key=key; this.val=val; } } int capacity; HashMap<Integer, Node> map; Node head, tail; public LRUCache(int capacity) { this.capacity=capacity; map = new HashMap<>(); head=new Node(0,0); tail=new Node(0,0); head.next=tail; tail.prev=head; } public int get(int key) { if(!map.containsKey(key)){ return -1; } Node node=map.get(key); remove(node); addToHead(node); return node.val; } public void put(int key, int value) { if(map.containsKey(key)){ Node cur = map.get(key); cur.val=value; remove(cur); addToHead(cur); }else{ if(map.size()==capacity){ Node deleNode = tail.prev; remove(deleNode); map.remove(deleNode.key); } Node node=new Node(key, value); map.put(key, node); addToHead(node); } } void remove(Node node){ node.prev.next = node.next; node.next.prev = node.prev; } void addToHead(Node node){ node.next=head.next; node.prev=head; head.next=node; node.next.prev=node; } } /** * 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); */

138. 随机链表的复制 - 力扣(LeetCode)

简单思路:哈希表存储节点的副本节点

class Solution { public Node copyRandomList(Node head) { HashMap<Node, Node> map = new HashMap<>(); Node cur = head; // a->a' while(cur != null){ map.put(cur, new Node(cur.val)); cur=cur.next; } cur=head; //a'.next=(a.next)' while(cur!=null){ map.get(cur).next=map.get(cur.next); map.get(cur).random=map.get(cur.random); cur=cur.next; } return map.get(head); } }

24. 两两交换链表中的节点 - 力扣(LeetCode)

和k个一组翻转类似,dummy 节点 + prev/cur/aft 三指针

换序+prev和cur、aft位置搬运

ListNode aft = cur.next.next; // 备份剩余链表头
prev.next = cur.next; // ┐
cur.next.next = cur; // ├ 三步完成换序 + 接回
cur.next = aft; // ┘
prev = cur; // ┐
cur = aft; // ┘ 两步移动指针

class Solution { public ListNode swapPairs(ListNode head) { if(head==null||head.next==null) return head; ListNode dim = new ListNode(0,head); ListNode prev = dim; ListNode cur = head; while(cur != null && cur.next != null){ ListNode aft = cur.next.next; prev.next = cur.next; cur.next.next = cur; cur.next = aft; prev = cur; cur = aft; } return dim.next; } }

19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)

容易错:虚拟节点加上,返回不能直接返回head,fast先走的步数是n+1

fast先走n+1步,再同时走,fast还需要len-n步停止,slow走len-n步,还剩余n个节点,正好到达倒数第n+1个节点处

class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { if(head.next==null)return null; ListNode dum = new ListNode(-1); dum.next=head; ListNode fast = dum; ListNode slow = dum; for(int i=0;i<n+1;i++){ fast=fast.next; } while(fast!=null){ fast=fast.next; slow=slow.next; } slow.next = slow.next.next; return dum.next; } }

2. 两数相加 - 力扣(LeetCode)

三种情况需要循环:

  • l1还有节点
  • l2还有节点
  • carry还有进位
class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { int jinwei =0; ListNode dumHead = new ListNode(-1); ListNode prev = dumHead; while(l1 != null || l2 !=null || jinwei > 0){ int x = l1 != null ? l1.val : 0; int y = l2 != null ? l2.val : 0; int curval = jinwei+x+y; jinwei = curval /10; int gewei = curval % 10; prev.next = new ListNode(gewei); prev = prev.next; if(l1 !=null) l1 = l1.next; if(l2 !=null) l2 = l2.next; } return dumHead.next; } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 13:26:44

hyperframes多帧点云堆叠与时间戳特征在3D目标检测中的实践

做3D点云目标检测的老哥应该都听过hyperframes这个词&#xff0c;它最早出现在PointPillars论文里&#xff0c;解决的是单帧激光雷达点云信息不足的问题。但说实话&#xff0c;论文提得很简略&#xff0c;很多开源库也默认不启用&#xff0c;真正要把它接入自己的训练pipeline&…

作者头像 李华
网站建设 2026/10/15 13:26:41

SAP Build PA实现高效业务流程扩展与回调机制

1. 项目背景与核心价值在SAP S/4HANA Cloud的标准业务流程中&#xff0c;系统预置的标准化操作往往无法完全满足企业个性化需求。当我们需要在采购审批、财务过账或销售订单处理等关键业务节点插入定制逻辑时&#xff0c;传统开发方式面临三大挑战&#xff1a;云环境的代码修改…

作者头像 李华
网站建设 2026/10/15 13:26:09

SpringBoot3与MyBatis-Plus 3.5.9整合实战指南

1. 项目概述&#xff1a;SpringBoot3与MyBatis-Plus 3.5.9整合实践最近在重构一个老项目的持久层时&#xff0c;我选择了SpringBoot 3.x MyBatis-Plus 3.5.9这套技术组合。作为Java生态中最主流的ORM框架组合之一&#xff0c;这套方案在开发效率、性能表现和可维护性上达到了很…

作者头像 李华
网站建设 2026/10/15 13:26:05

Recharts动态资源图:秒级时间序列可视化实战

1. 项目概述&#xff1a;为什么一张“会呼吸”的资源图比静态图表更值得投入时间你有没有遇到过这样的场景&#xff1a;在某个后台系统里&#xff0c;盯着CPU使用率那条平直的绿线发呆&#xff0c;心里却清楚——这数据可能已经滞后三分钟了&#xff1b;或者刚切到内存监控页&a…

作者头像 李华
网站建设 2026/10/15 13:26:01

OpenClaw 总体架构技术拆解:从 Gateway 到 Agent 的 WebSocket 会话链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/15 13:25:58

context-mode:本地AI上下文工程实践与SQLite+FTS5+BM25落地指南

1. “context-mode”到底是什么&#xff1f;别被术语绕晕&#xff0c;它本质是让AI真正“听懂上下文”的工程实践最近在多个技术社区和开源项目里频繁看到“context-mode”这个词&#xff0c;尤其和MCP、SQLite、FTS5、BM25这些词绑在一起出现。很多人第一反应是——这又是个新…

作者头像 李华