当前位置: 首页 > news >正文

【算法】day14 链表

1、回文链表 hot

题目:234. 回文链表 - 力扣(LeetCode)

分析

法一:先放到数组,再双指针对比。时间复杂度 O(n+1/2n)=O(n),空间复杂度 O(n)。

法二,递归:先递归判断两边是不是回文,递归出来再判断中间是不是回文。先记录 head,再从 head 开始递归到 tail,tail 与 head 层层从边缘到中间比较。时间复杂度:递归遍历 O(n),再双向遍历 O(2n),共 O(n)。空间复杂度:栈深度 O(n)。

法三:先快慢指针获取中间节点,再翻转后半部分节点,对比完了再翻转回去。时间复杂度 O(获取中点1/2n+翻转1/2n+对比1/2n+翻转1/2n) = O(n),空间复杂度 O(1)。缺点:因为对原链表进行了修改,所以多线程时对链表的操作要加锁。

代码

法二,递归:

/*** 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 {private ListNode front; // 记录左节点public boolean isPalindrome(ListNode head) {front = head;return isCycle(head);}public boolean isCycle(ListNode cur) {if (cur == null) return true; // 递归结束条件if (!isCycle(cur.next)) return false; // 靠两边的节点不满足回文,返回 falseif (front.val != cur.val) return false; // 靠中间的不满足回文,返回 falsefront = front.next; // 更新左节点,比较下一对return true;}
}

法三:

/*** 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 boolean isPalindrome(ListNode head) {// 1. 快慢指针获取中间节点ListNode middle = getMiddle(head);// 2. 把中间结点后的链表翻转reserve(middle);// 3. 对比ListNode t1 = head, t2 = middle.next;boolean flag = true;while (t2 != null) {if (t1.val != t2.val) {flag = false;break;}t1 = t1.next;t2 = t2.next;}// 4. 把链表翻转回去,恢复原样reserve(middle);return flag;}public ListNode getMiddle (ListNode head) {if (head == null || head.next == null) return head;ListNode slow = head, fast = head.next;while (fast != null && fast.next != null) {slow = slow.next;fast = fast.next.next;}return slow;}public void reserve (ListNode head) {ListNode t = head.next;head.next = null;while (t != null) {ListNode next = t.next;t.next = head.next;head.next = t;t = next;}}
}

2、随机链表的复制 hot

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

分析:对于每个节点,我们需要访问并创建其下一个节点和随机节点,并插入新链表中。但是因为是随机节点,所以我们并不知道下一个节点/随机节点是否已经在之前被创建,如果不进行判断就会创建并连接多余的节点。当然也可以不判断,先遍历一遍创建完整链表,把旧-新节点对放到 map;再遍历一遍每个节点的随机节点,从 map 中取出对应的新节点进行连接。

时间复杂度 O(2n) = O(n),空间复杂度 哈希表 O(n)。

代码

/*
// Definition for a Node.
class Node {int val;Node next;Node random;public Node(int val) {this.val = val;this.next = null;this.random = null;}
}
*/class Solution {public Node copyRandomList(Node head) {Map<Node, Node> map = new HashMap<>();// 1. 创建正常链表Node t = head;Node newHead = new Node(0), tail = newHead;while (t != null) {Node node = new Node(t.val);map.put(t, node);tail.next = node;tail = tail.next;t = t.next;}// 2. 连接随机节点t = head;tail = newHead.next;while (t != null) {Node node = map.get(t.random);tail.random = node;tail = tail.next;t = t.next;}return newHead.next;}
}

3、LRU 缓存 hot

题目:146. LRU 缓存 - 力扣(LeetCode)

分析:哈希表(频繁查找 key 对应的节点 O(1))+双向链表(频繁删除尾节点,单链表无法获取尾节点前驱)删插都是 O(1)。

  • LRUCache(int capacity):初始化容量、双向链表。
  • int get(int key):哈希表里查 key 对应的 node,没有则返回 -1;有则将其移动到链头(最近使用),并返回 value。
  • void put(int key, int value):哈希表查 key 对应的 node,有则将其移动到链头,并更新 value;没有则插入到链头,如果size超过了容量,就删除链尾最久没有使用的 node。
  • 使用空值的头结点、尾节点,方便删除、插入。

代码

class LRUCache {class DoubleListNode {int key;int val;DoubleListNode pre;DoubleListNode next;public DoubleListNode () {}public DoubleListNode (int key, int val) {this.key = key;this.val = val;}}private DoubleListNode head, tail;private int size, capacity;private Map<Integer, DoubleListNode> map = new HashMap<>();public LRUCache(int capacity) {size = 0;this.capacity = capacity;head = new DoubleListNode();tail = new DoubleListNode();head.next = tail;tail.pre = head;}public int get(int key) {DoubleListNode node = map.get(key);// 存在则移到链头,返回 valif (node != null) {int val = node.val;removeToHead(node);return val;}// 不存在,返回 -1return -1;}public void put(int key, int val) {DoubleListNode node = map.get(key);// 如果存在,则更新值,并移到链头if (node != null) {node.val = val;removeToHead(node);return;}// 不存在,则创建新节点插到链头DoubleListNode newNode = new DoubleListNode(key, val);map.put(key, newNode);insertToHead(newNode);size++;// 如果链表大小超过容量,删除尾部最久没使用的if (size > capacity) {deleteTail();size--;}}public void removeToHead(DoubleListNode node) {delete(node);insertToHead(node);}public void delete(DoubleListNode node) {DoubleListNode pre = node.pre;DoubleListNode next = node.next;pre.next = next;next.pre = pre;}public void insertToHead(DoubleListNode node) {node.next = head.next;node.next.pre = node;head.next = node;node.pre = head;}public void deleteTail() {DoubleListNode deleteNode = tail.pre;DoubleListNode pre = deleteNode.pre;map.remove(deleteNode.key);pre.next = tail;tail.pre = pre;}
}/*** 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);*/
http://www.dtcms.com/a/541476.html

相关文章:

  • 手机建设网站赚钱专业seo站长工具
  • 网站建设项目申请嵌入式工程师证书怎么考
  • [vscode] vscode的python解释器问题
  • 告别卡顿与等待,Rancher Vai 让集群操作“秒响应”
  • 【vscode】Eigen可视化配置
  • VSCode Copilot 魔改对比:智谱 GLM-4.6 与其他大模型接入流程差异解析
  • PyTorch2 Python深度学习 - TensorBoard可视化工具
  • wordpress首页分页函数网站专业优化
  • 雅奇小蘑菇做网站好不好用家居定制公司股票
  • 安卓进阶——UI控件
  • Android 四大组件——Activity
  • 照片书哪个网站做的好哪家网站开发培训好
  • wordpress小说网站模板下载地址光辉网络 石家庄网站建设
  • 网站建设可信赖环球资源网的网站特色
  • 西安网站开发高端网站开发中企动力是干嘛的
  • 浅谈什么是微前端
  • AtCoder Beginner Contest 429(ABCDEF)
  • 好用的GEO优化引擎服务商
  • 做网站那个平台网站制作网站建设案例
  • 搜索引擎主题网站模板网络架构有哪几层
  • Linux 驱动开发中,主设备号和次设备号不同的两个驱动能否正常工作
  • 人和AI的分工模式!
  • 模板网站与 定制网站的 对比中企动力主要做什么的
  • ECharts 3D柱状图组件开发实战:Bar3D.vue 完整解析
  • 手机App上的轮播图是如何实现的—探究安卓轮播图
  • Day71 MQTT数据上传与ARM端交叉编译部署全链路实践
  • 2024年 5月 每日分享
  • 漯河英文网站建设创建私人网站
  • 网站开发学哪一个好电子商务网站建设模板
  • 5.4 大数据方法论与实践指南-存储-安全合规