目录
上一篇博客中 -----链表初级详解------我们讲了链表的基本操作,看上去很简单,掌握了基础的增删查改的思想。但这好比三原色,通过各种组合,千变万化。现在我们就看看链表有什么进阶的东西可用学学,了解一下:玩链表,就是玩指针!的具体思想哈哈哈。
单链表反转

思路:玩链表就是玩指针,链表的反转其实就是几个指针的移动。我们可以用递归和迭代分别作答。
private ListNode reverse(ListNode head){
// 递归到到数第二个节点,返回新的头结点
if (head.next == null) {
return head;
}
ListNode newHead = reverse(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
//迭代
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null, cur = head;
while (cur != null) {
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}
链表中环的检测
怎么理解这个环结构呢?关键是要想明白,环结构相比无环结构,会有什么新现象。
思路一:一个指针在链表里旅游,去过的地方都标记起来。
如果存在环结构,指针就会去到以前标记过的地方;
如果环结构不存在,指针去的一直都是没标记过的地方。
于是哈希应运而生。
//法一:哈希表
public boolean hasCycle(ListNode head) {
Set<ListNode> nodesSeen = new HashSet<>();
while (head != null) {
if (nodesSeen.contains(head)) {
return true;
} else {
nodesSeen.add(head);
}
head = head.next;
}
return false;
}
思路二:两个指针在链表里旅游,一个快一个慢,
如果存在环结构,两个指针就一定会相遇
如果不存在环结构,两个指针就一定不会相遇
就像在操场跑步一样,跑得快的和跑得慢的,一定会相遇,只是不知道跑多少圈才相遇而已。
于是快慢指针应运而生。
//法二:快慢指针
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) {
return false;
}
ListNode slow = head;
ListNode fast = head.next;
while (slow != fast) {
if (fast == null || fast.next == null) {
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
}
两个有序的链表合并

普通的思路可能会新开一个链表,但作为能省就省的我们,还是有更好的方法的(这里不是说能不开辟空间就打死都不开辟,有时候用空间换时间是一种大智慧。)
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1 == null) {
return l2;
}
if(l2 == null) {
return l1;
}
if(l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
}
删除链表倒数第n个结点
这个很简单,用快慢指针就能搞定,让快指针先走n步,

public ListNode removeNthFromEnd(ListNode head, int n) {
if(head==null||n<0) return null;
ListNode dummy = new ListNode(0);
dummy.next=head;
ListNode fast=dummy;
ListNode slow=dummy;
for(int i =0;i<=n;i++){
fast=fast.next;
}
while(fast!=null){
slow=slow.next;
fast=fast.next;
}
slow.next=slow.next.next;
return dummy.next;
}
求链表的中间结点

这个也很简单,用快慢指针就能搞定,让快指针的速度为慢指针的两倍,这样快指针到底了,慢指针不就刚好停在链表中点处么。
ListNode fast = head;
ListNode slow = head;
// 根据快慢指针,找到链表的中点
while(fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}

199

被折叠的 条评论
为什么被折叠?



