两数相加:逐位相加
两个链表逐位走,当前位 % 10,进位 / 10,剩余 carry 标记进位
java
public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode res = new ListNode(0);
ListNode cur = res;
int carry = 0;//进位标识
//l1和l2全为null时跳出循环
while(l1 != null || l2 != null){
int x = (l1 != null) ? l1.val : 0;
int y = (l2 != null) ? l2.val : 0;
int sum = x + y + carry;
carry = sum / 10;
int val = sum % 10;
cur.next = new ListNode(val);
cur = cur.next;
if(l1 != null) l1 = l1.next;
if(l2 != null) l2 = l2.next;
}
if(carry == 1){
cur.next = new ListNode(1);
}
return res.next;
}
删除链表的倒数第N个节点:快慢指针 + 固定间距
注意考虑删除节点为第一个节点的情况->虚拟头节点
java
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode fast = dummy;
ListNode slow = dummy;
for (int i = 0; i <= n; i++) {
fast = fast.next;
}
while (fast != null) {
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummy.next;
}
两两交换链表中的节点:两两一组判别
- 注意先后顺序,right.next 的改变应该在 left = right.next 之前

java
public static ListNode swapPairs(ListNode head) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode prev = dummy;
while (prev.next != null && prev.next.next != null) {
ListNode left = prev.next;
ListNode right = prev.next.next;
prev.next = right;
left.next = right.next;
right.next = left;
prev = left;
}
return dummy.next;
}
排序链表:归并排序
使用插入排序,会进行两层循环,结果超时
① 找中点
↓
② 切成两个链表
↓
③ 左右分别递归排序
↓
④ merge 两个有序链表
java
public static ListNode sortList(ListNode head) {
if(head == null || head.next == null){
return head;
}
//先使用快慢指针将链表分为两半
ListNode slow = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null){
slow = slow.next;
fast = fast.next.next;
}
ListNode p1 = head;
ListNode p2 = slow.next;
slow.next = null;
p1 = sortList(p1);
p2 = sortList(p2);
//合并两个有序链表
return mergeTwoLists(p1, p2);
}
//mergeTwoLists方法
public static ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(0);
ListNode head = dummy;
while(l1 != null && l2 != null){
if(l1.val < l2.val){
head.next = l1;
l1 = l1.next;
}else{
head.next = l2;
l2 = l2.next;
}
head = head.next;
}
head.next = l1 != null ? l1 : l2;
return dummy.next;
}
LRU缓存

-
addToHead=这个节点现在不在链表里,把它插到头部
-
moveToHead=这个节点已经在链表里,先删掉,再重新插到头部
-
注意进行区分,否则新节点会空指针异常
java
public class LRUCache {
private class DListNode{
int key;
int val;
DListNode prev;
DListNode next;
public DListNode(int key, int val){
this.key = key;
this.val = val;
}
}
int capacity;//缓存容量
int size;//当前已经存在的节点数量
Map<Integer, DListNode> map = new HashMap<>();
DListNode dummy_head;
DListNode dummy_tail;
public LRUCache(int capacity) {
this.capacity = capacity;
size = 0;
dummy_head = new DListNode(-1, -1);
dummy_tail = new DListNode(-1, -1);
dummy_head.next = dummy_tail;
dummy_tail.prev = dummy_head;
}
public int get(int key) {
if (!map.containsKey(key)) {
return -1;
}
DListNode node = map.get(key);
moveToHead(node);
return node.val;
}
public void put(int key, int value) {
//如果key存在,直接更新值
if (map.containsKey(key)) {
DListNode node = map.get(key);
node.val = value;
moveToHead(node);
return;
}
if (size == capacity) {
//如果缓存已满,删除尾部节点
DListNode tail = dummy_tail.prev;
map.remove(tail.key);
removeNode(tail);
size--;
}
//添加新节点到头部
DListNode node = new DListNode(key, value);
map.put(key, node);
addToHead(node);
size++;
}
private void removeNode(DListNode node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
//将节点添加到头部(节点原来不存在)
private void addToHead(DListNode node) {
node.prev = dummy_head;
node.next = dummy_head.next;
dummy_head.next.prev = node;
dummy_head.next = node;
}
//将节点移动到头部(节点原来存在)
private void moveToHead(DListNode node) {
removeNode(node);
addToHead(node);
}
}