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→…
要求使用原地算法,不能只改变节点内部的值,需要对实际的节点进行交换。

  1. public class Solution {
  2. public void reorderList(ListNode head) {
  3. if(head == null || head.next == null)
  4. return;
  5. // 快满指针找到中间节点
  6. ListNode fast = head;
  7. ListNode slow = head;
  8. while(fast.next != null && fast.next.next != null){
  9. fast = fast.next.next;
  10. slow = slow.next;
  11. }
  12. // 拆分链表,并反转中间节点之后的链表
  13. ListNode after = slow.next;
  14. slow.next = null;
  15. ListNode pre = null;
  16. while(after != null){
  17. ListNode temp = after.next;
  18. after.next = pre;
  19. pre = after;
  20. after = temp;
  21. }
  22. // 合并两个链表
  23. ListNode first = head;
  24. after = pre;
  25. while(first != null && after != null){
  26. ListNode ftemp = first.next;
  27. ListNode aftemp = after.next;
  28. first.next = after;
  29. first = ftemp;
  30. after.next = first;
  31. after = aftemp;
  32. }
  33. }
  34. }

2.翻转链表

利用栈来翻转链表

  1. import java.util.*;
  2. public class Solution {
  3. public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
  4. //用来存储链表中节点的值。
  5. Stack<Integer> reverse = new Stack<>();
  6. while(listNode != null){
  7. reverse.push(listNode.val);
  8. listNode = listNode.next;
  9. }
  10. //创建的题目要求的数据类型来存储反向的节点值。
  11. ArrayList<Integer> result = new ArrayList<>();
  12. while(!reverse.isEmpty()){
  13. //将值从栈中弹出,并添加到ArrayList中
  14. result.add(reverse.pop());
  15. }
  16. return result;
  17. }
  18. }

递归翻转

  1. import java.util.*;
  2. public class Solution {
  3. ArrayList<Integer> list = new ArrayList();
  4. public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
  5. if(listNode!=null){
  6. printListFromTailToHead(listNode.next);
  7. list.add(listNode.val);
  8. }
  9. return list;
  10. }
  11. }

3.LRU

哈希表+双向链表

  1. public class LRUCache {
  2. private int size; // 当前容量
  3. private int capacity; // 限制大小
  4. private Map<Integer, DoubleQueueNode> map; // 数据和链表中节点的映射
  5. private DoubleQueueNode head; // 头结点 避免null检查
  6. private DoubleQueueNode tail; // 尾结点 避免null检查
  7. public LRUCache(int capacity) {
  8. this.capacity = capacity;
  9. this.map = new HashMap<>(capacity);
  10. this.head = new DoubleQueueNode(0, 0);
  11. this.tail = new DoubleQueueNode(0, 0);
  12. this.head.next = tail;
  13. }
  14. public Integer get(Integer key) {
  15. DoubleQueueNode node = map.get(key);
  16. if (node == null) {
  17. return null;
  18. }
  19. // 数据在链表中,则移至链表头部
  20. moveToHead(node);
  21. return node.val;
  22. }
  23. public Integer put(Integer key, Integer value) {
  24. Integer oldValue;
  25. DoubleQueueNode node = map.get(key);
  26. if (node == null) {
  27. // 淘汰数据
  28. eliminate();
  29. // 数据不在链表中,插入数据至头部
  30. DoubleQueueNode newNode = new DoubleQueueNode(key, value);
  31. DoubleQueueNode temp = head.next;
  32. head.next = newNode;
  33. newNode.next = temp;
  34. newNode.pre = head;
  35. temp.pre = newNode;
  36. map.put(key, newNode);
  37. size++;
  38. oldValue = null;
  39. } else {
  40. // 数据在链表中,则移至链表头部
  41. moveToHead(node);
  42. oldValue = node.val;
  43. node.val = value;
  44. }
  45. return oldValue;
  46. }
  47. public Integer remove(Integer key) {
  48. DoubleQueueNode deletedNode = map.get(key);
  49. if (deletedNode == null) {
  50. return null;
  51. }
  52. deletedNode.pre.next = deletedNode.next;
  53. deletedNode.next.pre = deletedNode.pre;
  54. map.remove(key);
  55. return deletedNode.val;
  56. }
  57. // 将节点插入至头部节点
  58. private void moveToHead(DoubleQueueNode node) {
  59. node.pre.next = node.next;
  60. node.next.pre = node.pre;
  61. DoubleQueueNode temp = head.next;
  62. head.next = node;
  63. node.next = temp;
  64. node.pre = head;
  65. temp.pre = node;
  66. }
  67. private void eliminate() {
  68. if (size < capacity) {
  69. return;
  70. }
  71. // 将链表中最后一个节点去除
  72. DoubleQueueNode last = tail.pre;
  73. map.remove(last.key);
  74. last.pre.next = tail;
  75. tail.pre = last.pre;
  76. size--;
  77. last = null;
  78. }
  79. }
  80. // 双向链表节点
  81. class DoubleQueueNode {
  82. int key;
  83. int val;
  84. DoubleQueueNode pre;
  85. DoubleQueueNode next;
  86. public DoubleQueueNode(int key, int val) {
  87. this.key = key;
  88. this.val = val;
  89. }
  90. }