1.重排链表
将给定的单链表 L\ L L: L0→L1→…→Ln−1→LnL0→L_1→…→L{n-1}→L nL0→L1→…→Ln−1→Ln
重新排序为:L0→Ln→L1→Ln−1→L2→Ln−2→…L_0→L_n →L_1→L{n-1}→L2→L{n-2}→…L0→Ln→L1→Ln−1→L2→Ln−2→…
要求使用原地算法,不能只改变节点内部的值,需要对实际的节点进行交换。
public class Solution {public void reorderList(ListNode head) {if(head == null || head.next == null)return;// 快满指针找到中间节点ListNode fast = head;ListNode slow = head;while(fast.next != null && fast.next.next != null){fast = fast.next.next;slow = slow.next;}// 拆分链表,并反转中间节点之后的链表ListNode after = slow.next;slow.next = null;ListNode pre = null;while(after != null){ListNode temp = after.next;after.next = pre;pre = after;after = temp;}// 合并两个链表ListNode first = head;after = pre;while(first != null && after != null){ListNode ftemp = first.next;ListNode aftemp = after.next;first.next = after;first = ftemp;after.next = first;after = aftemp;}}}
2.翻转链表
利用栈来翻转链表
import java.util.*;public class Solution {public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {//用来存储链表中节点的值。Stack<Integer> reverse = new Stack<>();while(listNode != null){reverse.push(listNode.val);listNode = listNode.next;}//创建的题目要求的数据类型来存储反向的节点值。ArrayList<Integer> result = new ArrayList<>();while(!reverse.isEmpty()){//将值从栈中弹出,并添加到ArrayList中result.add(reverse.pop());}return result;}}
递归翻转
import java.util.*;public class Solution {ArrayList<Integer> list = new ArrayList();public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {if(listNode!=null){printListFromTailToHead(listNode.next);list.add(listNode.val);}return list;}}
3.LRU
哈希表+双向链表
public class LRUCache {private int size; // 当前容量private int capacity; // 限制大小private Map<Integer, DoubleQueueNode> map; // 数据和链表中节点的映射private DoubleQueueNode head; // 头结点 避免null检查private DoubleQueueNode tail; // 尾结点 避免null检查public LRUCache(int capacity) {this.capacity = capacity;this.map = new HashMap<>(capacity);this.head = new DoubleQueueNode(0, 0);this.tail = new DoubleQueueNode(0, 0);this.head.next = tail;}public Integer get(Integer key) {DoubleQueueNode node = map.get(key);if (node == null) {return null;}// 数据在链表中,则移至链表头部moveToHead(node);return node.val;}public Integer put(Integer key, Integer value) {Integer oldValue;DoubleQueueNode node = map.get(key);if (node == null) {// 淘汰数据eliminate();// 数据不在链表中,插入数据至头部DoubleQueueNode newNode = new DoubleQueueNode(key, value);DoubleQueueNode temp = head.next;head.next = newNode;newNode.next = temp;newNode.pre = head;temp.pre = newNode;map.put(key, newNode);size++;oldValue = null;} else {// 数据在链表中,则移至链表头部moveToHead(node);oldValue = node.val;node.val = value;}return oldValue;}public Integer remove(Integer key) {DoubleQueueNode deletedNode = map.get(key);if (deletedNode == null) {return null;}deletedNode.pre.next = deletedNode.next;deletedNode.next.pre = deletedNode.pre;map.remove(key);return deletedNode.val;}// 将节点插入至头部节点private void moveToHead(DoubleQueueNode node) {node.pre.next = node.next;node.next.pre = node.pre;DoubleQueueNode temp = head.next;head.next = node;node.next = temp;node.pre = head;temp.pre = node;}private void eliminate() {if (size < capacity) {return;}// 将链表中最后一个节点去除DoubleQueueNode last = tail.pre;map.remove(last.key);last.pre.next = tail;tail.pre = last.pre;size--;last = null;}}// 双向链表节点class DoubleQueueNode {int key;int val;DoubleQueueNode pre;DoubleQueueNode next;public DoubleQueueNode(int key, int val) {this.key = key;this.val = val;}}
