0,链表的结构
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
1,单链表反转
这里建议画图理解,画图之后,会更加直观
public ListNode reverse(ListNode head){
if(head == null)
return null;
ListNode temp = null;
while(head != null){
ListNode p = head.next;
head.next = temp;
temp = head;
head = p;
}
return temp;
}
2,链表中环的检测
让较快的指针走两步,较慢的指针走一步,如果存在环,那么它们肯定会相遇
public boolean checkCircle(ListNode head){
if(head == null)
return false;
ListNode fast = head;
ListNode slow = head;
//链表只存在一个节点的情况
if(head.next == null)
return false;
//链表只存在两个节点的情况
if(head.next.next == null)
return false;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(slow == fast){
return true;
}
}
return false;
}
3,两个有序的链表合并
这里用到递归的思想
public ListNode mergeList(ListNode head1,ListNode head2) {
if(head1 == null && head2 == null)
return null;
if(head1 == null)
return head2;
if(head2 == null)
return head1;
ListNode newHead = null;
if(head1.val <= head2.val){
newHead = head1;
newHead.next = mergeList(head1.next,head2);
}
else
{
newHead = head2;
newHead.next = mergeList(head1,head2.next);
}
return newHead;
}
4,删除链表中倒数第 k 个节点
这里可以设两个指针,一个为 fast, 一个为 slow,让 fast 指针先走 k-1 步,然后fast 走一步,slow 走一步。当 fast 走到链表的尾部时,slow 正好走到要删除节点的前一个节点。
public ListNode deleteKth(ListNode head, int k){
if(head == null || k <= 0)
return null;
ListNode fast = head;
ListNode slow = head;
// fast 节点多走一步,使 slow 走在要删除节点的前面一个节点
while(k >= 0 && fast != null){
fast = fast.next;
k--;
}
while(fast != null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return head;
}
5,求链表的中间节点
这里我用的是比较暴力的算法,直接先用一个节点走到链表的尾部,同时记录链表中节点的个数,这里设为 k 个节点。再重新建一个新的指针,走到 k / 2 处,即找到了链表的中间节点。
public ListNode midNode(ListNode head){
if(head == null)
return null;
int k = 0;
ListNode count = head;
ListNode midNode = head;
while(count != null){
count = count.next;
k++;
}
k = k / 2;
while(k > 0){
midNode = midNode.next;
k--;
}
return midNode;
}