参考文献 https://chienmy.gitbook.io/algorithm-pattern-java/shu-ju-jie-gou/linked_list
83 删除排序链表中重复元素
/**
* 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 ListNode deleteDuplicates(ListNode head) {
if(head==null) return null; // 注意考虑空指针输入情况
ListNode left = head;
ListNode right = head.next;
while(right!=null){
if(left.val==right.val){
right = right.next;
left.next = right;
}else{
left = left.next;
right = right.next;
}
}
return head;
}
}
82 删除排序链表中的重复元素II
/**
* 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 ListNode deleteDuplicates(ListNode head) {
if(head==null) return null;
if(head.next==null) return head;
ListNode dummynode = new ListNode(-1,head);
ListNode left = dummynode;
ListNode right = head;
while(right!=null && right.next!=null){
if(left.next.val == right.next.val){
if(right.next.next==null){
left.next = null;break; // 链表只有两个重复结点,删除后跳出循环
}
if(right.next.val == right.next.next.val){ // 删除奇数个重复结点
left.next.next = right.next.next;
}else{ // 删除偶数个
left.next = right.next.next;
right = left.next;
}
}else{
left = left.next;
right = right.next;
}
}
return dummynode.next;
}
}
206 反转链表
递归
/**
* 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 ListNode reverseList(ListNode head) {
if(head==null) return null;
if(head.next==null) return head;
ListNode revlist = reverseList(head.next);
head.next.next = head;
head.next = null;
return revlist;
}
}
迭代
/**
* 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 ListNode reverseList(ListNode head) {
if(head==null) return null;
ListNode pre = null;
ListNode cur = head;
while(cur!=null){
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
}
92 反转链表II
/**
* 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 ListNode reverseBetween(ListNode head, int left, int right) {
if(head==null) return null;
ListNode dummynode = new ListNode(-1,head);
ListNode front = dummynode;
for(int i=0;i<left-1;i++){
front = front.next;
}
ListNode pre,tail,cur;
pre = tail = front.next;
cur = pre.next;
for(int i= 0;i<(right-left);i++){
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
front.next = pre;
tail.next = cur;
return dummynode.next;
}
}
21 合并两个有序链表
递归
/**
* 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 ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1==null || l2==null) return l1==null ? l2 : l1;
if(l1.val <= l2.val){
l1.next = mergeTwoLists(l1.next,l2);
}else{
l2.next = mergeTwoLists(l2.next,l1);
}
return l1.val <= l2.val ? l1 : l2;
}
}
23 合并K个升序链表
/**
* 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 ListNode mergeKLists(ListNode[] lists) {
return merge(lists,0,lists.length - 1); // 分治,两个两个链表处理
}
public ListNode merge(ListNode[] lists,int begin,int end){
if(begin==end) return lists[begin]; // 说明只有一个链表元素
if(begin>end) return null; // 不存在
int mid = (begin+end) >> 1; // 有符号右移一位 0001;相当于平均值向下取整
return mergeTwoLists( merge(lists,begin,mid) , merge(lists,mid+1,end) ); // 递归不断细分数组,让两个链表合并
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1==null || l2==null) return l1==null ? l2 : l1;
if(l1.val <= l2.val){
l1.next = mergeTwoLists(l1.next,l2);
}else{
l2.next = mergeTwoLists(l2.next,l1);
}
return l1.val <= l2.val ? l1 : l2;
}
}
876 链表的中间结点
快慢指针
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode middleNode(ListNode head) {
ListNode slow,fast;
slow = fast = head;
while(fast!=null && fast.next!=null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
}
143 重排链表
先找中间结点分成两个链表,将mid后面的链表反转后拼接两个链表
/**
* 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 void reorderList(ListNode head) {
ListNode midnode = middleNode(head);
ListNode right = midnode.next;
midnode.next = null;
ListNode rev = reverseList(right);
merge(head,rev);
}
public ListNode middleNode(ListNode head) {
ListNode slow,fast;
slow = fast = head;
while(fast!=null && fast.next!=null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
public ListNode reverseList(ListNode head) {
if(head==null) return null;
ListNode pre = null;
ListNode cur = head;
while(cur!=null){
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
public void merge(ListNode l1,ListNode l2){
ListNode l1_tmp;
ListNode l2_tmp;
while(l1!=null && l2!=null){
l1_tmp = l1.next;
l2_tmp = l2.next;
l1.next = l2;
l1 = l1_tmp;
l2.next = l1;
l2 = l2_tmp;
}
}
}
234 回文链表
快慢指针、反转链表
/**
* 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) {
ListNode slow,fast,pre,tmp,rev;
slow = fast = head;
rev = pre = null;
// 查找中间结点的同时反转前半部分链表
while(fast!=null && fast.next!=null){
fast = fast.next.next;
tmp = slow.next;
slow.next = pre;
pre = slow;
slow = tmp;
}
if(fast!=null){ // 奇数链表
rev = slow.next;
}else{ // 偶数链表
rev = slow;
}
// 比较两部分链表
while(rev!=null){
if(rev.val != pre.val) return false;
rev = rev.next;
pre = pre.next;
}
return true;
}
}
141 环形链表
快慢指针,快慢指针相同则有环,如果有环每走一步快慢指针距离会减 1
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
if(head==null || head.next==null) return false;
ListNode slow,fast;
slow = fast = head;
while(fast!=null){
fast = fast.next;
if(fast!=null){
fast = fast.next;
}
if(slow == fast) return true;
slow = slow.next;
}
return false;
}
}
142 环形链表II
快慢指针,快慢相遇之后,慢指针回到头,快慢指针步调一致一起移动,相遇点即为入环点
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head==null || head.next==null) return null;
ListNode slow ,fast;
slow = fast = head;
while(fast!=null && fast.next!=null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
slow = head;
while(fast!=slow){
slow = slow.next;
fast = fast.next;
}
return fast;
}
}
return null;
}
}
19 删除链表的倒数第N个结点
快慢指针,虚拟头结点;
先让fast走n步。
/**
* 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 ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummynode = new ListNode(-1,head);
ListNode slow , fast;
slow = fast = dummynode;
for(int i=0;i<n;i++){
fast = fast.next;
}
while(fast.next!=null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummynode.next;
}
}
138 复制带随机指针的链表
复制节点跟在原节点后面
/*
// 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) {
if(head == null) return null;
// 在每一原结点后克隆一个没有random的结点
Node cur = head;
while(cur!=null){
Node cloneNode = new Node(cur.val);
cloneNode.next = cur.next;
Node tmp = cur.next;
cur.next = cloneNode;
cur = tmp;
}
// 为克隆的结点根据原结点的random找其对应的random,根据原结点后跟着其克隆结点的特点操作
cur = head;
while(cur != null){
if(cur.random != null){ // 跳过random为null的原结点
cur.next.random = cur.random.next; // 克隆结点的random
}
cur = cur.next.next;
}
// 分开两条链表,返回克隆链表;
cur = head;
Node cloneHead = head.next;
while(cur != null && cur.next != null){
Node tmp = cur.next;
cur.next = cur.next.next;
cur = tmp;
}
return cloneHead;
}
}