两数相加
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
boolean carry = false;
ListNode dummy = new ListNode();
ListNode cur = dummy;
while (l1 != null || l2 != null || carry) {
int a = l1 == null ? 0 : l1.val;
int b = l2 == null ? 0 : l2.val;
int sum = carry ? a + b + 1 : a + b;
carry = sum / 10 == 1;
cur.next = new ListNode(sum%10);
cur = cur.next;
l1 = l1 == null ? l1 : l1.next;
l2 = l2 == null ? l2 : l2.next;
}
return dummy.next;
}
删除链表倒数第N个节点
//使用哨兵节点可以少一个判断和不用记录前驱节点
public ListNode removeNthFromEnd(ListNode head, int n) {
if (head == null) {
return head;
}
//快慢指针
ListNode dummy = new ListNode();
ListNode fast = head;
ListNode slow = dummy;
dummy.next = head;
while (n != 0) {
fast = fast.next;
n--;
}
while (fast != null) {
prev = slow;
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
return dummy.next;
}
//不使用哨兵节点就要记录前驱节点并判断前驱节点是否为空,如果前驱节点为空表示删除头结点
public ListNode removeNthFromEnd(ListNode head, int n) {
if (head == null) {
return head;
}
//快慢指针
ListNode dummy = head;
ListNode fast = head;
ListNode slow = head;
ListNode prev = null;
while (n != 0) {
fast = fast.next;
n--;
}
while (fast != null) {
prev = slow;
slow = slow.next;
fast = fast.next;
}
if (prev == null) {
dummy = dummy.next;
} else {
prev.next = slow.next;
}
return dummy;
}
两两交换链表的节点
迭代法
public ListNode swapPairs(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode dummy = new ListNode();
ListNode tail = dummy;
ListNode first = head;
ListNode second = head.next;
while (first != null && second != null) {
tail.next = second;//已经处理的链表尾节点指向第二个节点0->2->3->4
first.next = second.next;//第一个节点指向第三个节点 1->3->4
second.next = first;//第二个节点指向第一个节点 0->2->1->3->4
tail = first;
first = tail.next;
second = tail.next == null ? null : tail.next.next;
}
return dummy.next;
}
递归法
//第二个节点指向第一个节点,第一个节点指向已经处理的链表的头结点,从后往前交换,迭代是从前往后交换
public ListNode swapPairs(ListNode first) {
if (first == null || first.next == null) {
return head;
}
ListNode head = swapPairs(first.next.next);
ListNode second = first.next; //第二个节点
second.next = first; //第二个节点指向第一个节点
first.next = head; // 第一个节点指向已经处理的链表的头结点
return second;
}
分隔链表
public ListNode partition(ListNode head, int x) {
if (head == null || head.next == null) {
return head;
}
ListNode letter = new ListNode();
ListNode cur = letter;
ListNode greater = new ListNode();
ListNode cur1 = greater;
while (head != null) {
if (head.val < x) {
cur.next = new ListNode(head.val);
cur = cur.next;
} else {
cur1.next = new ListNode(head.val);
cur1 = cur1.next;
}
head = head.next;
}
cur.next = greater.next;
return letter.next;
}
反转链表||
头插法
public ListNode reverseBetween(ListNode head, int left, int right) {
if (head == null || head.next == null || right == left) {
return head;
}
int step = right - left;
ListNode dummy = new ListNode();
dummy.next = head;
ListNode cur = dummy.next;
ListNode tail = dummy;
while (left != 1) {
tail = cur;
cur = cur.next;
left--;
}
ListNode newHead = cur;
for (int i = 0; i < step; i++) {
ListNode insert = cur.next;
ListNode tailNext = tail.next; //当前反转链表的头结点 还未插入
tail.next = insert; //前半段的尾指向要插入的节点 1-> 3->4->5
cur.next = insert.next; //反转前的头结点指向要插入的节点的后一个节点 2-> 4->5
insert.next = tailNext; //要插入的节点指向当前反转链表的头结点 3-> 2->4->5
}
return dummy.next;
}
先断链,后反转最后拼接,反转可以迭代或者递归
public ListNode reverseBetween1(ListNode head, int left, int right) {
if (head == null || head.next == null || left == right) {
return head;
}
int step = right - left;
ListNode dummy = new ListNode();
dummy.next = head;
ListNode cur = dummy;
while (left != 1) {
cur = cur.next;
left--;
}
ListNode first = cur.next; //中间段的头结点
cur.next = null; //断开前半段
ListNode tmp = first;
while (step != 0) {
tmp = tmp.next;
step--;
}
ListNode next = tmp.next; //后半段
tmp.next = null; //断开后半段
ListNode reverseList = reverseList(first);
//找反转后的链表的尾部
ListNode tail = reverseList;
while (tail.next != null) {
tail = tail.next;
}
tail.next = next; //中间段和后半段连接
cur.next = reverseList;//前半段和中间段连接
return dummy.next;
}
//迭代反转
private ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode cur = head;
while (cur != null) {
ListNode next = cur.next;
cur.next = prev;
prev = cur;
cur = next;
}
return prev;
}
//递归反转
private ListNode reverseList(ListNode head) {
if (head.next == null) {
return head;
}
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
二叉树展开成链表
public void flatten(TreeNode root) {
while (root != null) {
//左子树不为空就要进行拼接
if (root.left != null) {
TreeNode leftConnect = root.left;
//找到左子树的最右节点
while (leftConnect.right != null) {
leftConnect = leftConnect.right;
}
TreeNode right = root.right; //右子树
leftConnect.right = right;//右子树拼到左子树的最右节点
root.right = root.left; //拼好的左子树作为根节点新的右子树
root.left = null; //清空左子树
}
root = root.right; //遍历下一个右节点
}
}
链表插入排序
//用以一个前驱节点pre来找到需要插入的位置,找到第一个满足 pre.next >= cur.val 的前驱节点。 将cur插入其后面
public ListNode insertionSortList(ListNode head) {
ListNode dummy = new ListNode();
dummy.next = head;
ListNode tail = head; //已排序链表尾部
ListNode insert = head.next; //插入节点
while (insert != null) {
//插入节点比已排序链表尾部大就跳过
if (insert.val > tail.val) {
tail = tail.next;
} else {
ListNode prev = dummy;
//从前往后找到一个prev是prev < insert < prev.next
while (prev.next.val < insert.val) {
prev = prev.next;
}
//插入
ListNode next = prev.next;
prev.next = insert;
tail.next = insert.next;
insert.next = next;
}
insert = tail.next;
}
return dummy.next;
}
LRU缓存机制
双向链表+HashMap
put一个元素,如果本来就有就移到链表头部,使用先删除原来的,再添加的方式移动
如果没有就直接添加到链表头部,不用删除
get一个元素,如果有就移到链表头部,使用先删除原来的,再添加的方式移动
缓存满了删除链表尾部的元素
使用哨兵节点可以不用在删除的时候判断删除的是头结点还是尾节点,和添加的时候不用判断链表是否为空
不使用哨兵节点就要判断删除的是头结点还是尾节点,和添加的时候判断链表是否为空,不然的话为出现空指针异常
LinkedList没有用到哨兵节点
//使用哨兵节点
public class MyLRUCache {
int cap;
int size;
DoubleListNode tail; //tail的next为空
DoubleListNode head; //head的prev为空
Map<Integer,DoubleListNode> map;
public MyLRUCache(int capacity) {
map = new HashMap<>();
cap = capacity;
size = 0;
tail = new DoubleListNode(); //尾哨兵节点
head = new DoubleListNode(); //头哨兵节点
tail.prev = head;
head.next = tail;
}
public void moveToHead(DoubleListNode node) {
removeNode(node);
addToHead(node);
}
public void addToHead(DoubleListNode node) {
DoubleListNode oldFirst = head.next;
head.next = node;
node.prev = head;
node.next = oldFirst;
oldFirst.prev = node;
size++;
}
public DoubleListNode removeTail() {
DoubleListNode last = tail.prev;
removeNode(last);
return last;
}
public void removeNode(DoubleListNode node) {
DoubleListNode next = node.next;
DoubleListNode prev = node.prev;
prev.next = next;
next.prev = prev;
size--;
}
public int get(int key) {
if (map.containsKey(key)) {
DoubleListNode node = map.get(key);
moveToHead(node);
return node.val;
}
return -1;
}
public void put(int key, int value) {
//原来有key就执行更新操作
if (map.containsKey(key)) {
DoubleListNode node = map.get(key);
node.val = value;
moveToHead(node);
//没有就执行新增操作
} else {
DoubleListNode node = new DoubleListNode(key, value);
addToHead(node);
map.put(key,node);
}
if (size > cap) {
DoubleListNode oldLast = removeTail();
map.remove(oldLast.key);
}
}
class DoubleListNode {
public int key;
public int val;
public DoubleListNode next;
public DoubleListNode prev;
public DoubleListNode(int key, int x) {
this.key = key;
val = x;
}
public DoubleListNode() {
}
}
}
//不使用哨兵节点
public class MyNewLRUCache {
int cap;
int size;
DoubleListNode tail; //tail的next为空
DoubleListNode head; //head的prev为空
Map<Integer, DoubleListNode> map;
public MyNewLRUCache(int capacity) {
map = new HashMap<>();
cap = capacity;
size = 0;
}
public void moveToHead(DoubleListNode node) {
removeNode(node);
addToHead(node);
}
public void addToHead(DoubleListNode node) {
DoubleListNode oldFirst = head;
node.next = oldFirst;
head = node;
//链表为空
if (oldFirst == null) {
tail = node;
} else {
oldFirst.prev = node;
}
size++;
}
public DoubleListNode removeTail() {
DoubleListNode oldLast = tail;
// DoubleListNode newLast = tail.prev;
// tail = newLast;
// //链表只有一个节点
// if (newLast == null) {
// head = null;
// } else {
// newLast.next = null;
// }
// size--;
removeNode(oldLast);
return oldLast;
}
public void removeNode(DoubleListNode node) {
DoubleListNode next = node.next;
DoubleListNode prev = node.prev;
//删除的是头结点
if (prev == null) {
head = next;
} else {
prev.next = next;
node.prev = null;
}
//删除的是尾节点
if (next == null) {
tail = prev;
} else {
next.prev = prev;
node.next = null;
}
size--;
}
public int get(int key) {
if (map.containsKey(key)) {
DoubleListNode node = map.get(key);
moveToHead(node);
return node.val;
}
return -1;
}
public void put(int key, int value) {
//原来有key就执行更新操作
if (map.containsKey(key)) {
DoubleListNode node = map.get(key);
node.val = value;
moveToHead(node);
//没有就执行新增操作
} else {
DoubleListNode node = new DoubleListNode(key, value);
addToHead(node);
map.put(key,node);
}
if (size > cap) {
DoubleListNode oldLast = removeTail();
map.remove(oldLast.key);
}
}
class DoubleListNode {
public int key;
public int val;
public DoubleListNode next;
public DoubleListNode prev;
public DoubleListNode(int key, int x) {
this.key = key;
val = x;
}
public DoubleListNode() {
}
}
}
排序链表
//自底而上合并,递归
public ListNode sortList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode slow = head;
ListNode fast = head.next;
//找中点
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
ListNode right = slow.next;
slow.next = null;
ListNode l = sortList(head);
ListNode r = sortList(right);
return mergeTwoList(l,r);
}
public ListNode mergeTwoList(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode();
ListNode cur = dummy;
while (l1 != null && l2 != null) {
if (l1.val < l2.val) {
cur.next = l1;
l1 = l1.next;
} else {
cur.next = l2;
l2 = l2.next;
}
cur = cur.next;
}
cur.next = l1 == null ? l2 : l1;
return dummy.next;
}
奇偶链表
public ListNode oddEvenList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode dummy = new ListNode();
ListNode oddHead = new ListNode();
ListNode oddTail = oddHead;
ListNode evenHead = new ListNode();
ListNode evenTail = evenHead;
int count = 1;
while (head != null) {
//奇数
if (count % 2 != 0) {
oddTail.next = head;
oddTail = oddTail.next;
} else {
evenTail.next = head;
evenTail = evenTail.next;
}
head = head.next;
count++;
}
dummy.next = oddHead.next;
evenTail.next = null; //清空偶链表尾部后面的节点
oddTail.next = evenHead.next;
return dummy.next;
}
二叉搜索树转双向循环链表
//中序遍历
Node first;
Node prev;
public Node treeToDoublyList(Node root) {
if (root == null) {
return root;
}
Node node = treeToDoublyListDfs(root);
first.left = prev;
prev.right = first;
return first;
}
public Node treeToDoublyListDfs(Node cur) {
if (cur == null) {
return cur;
}
treeToDoublyListDfs(cur.left);
if (prev != null) {
cur.left = prev;
prev.right = cur;
} else {
first = cur;
}
prev = cur;
treeToDoublyListDfs(cur.right);
return cur;
}