JZ52 两个链表的第一个公共结点 ⭐
思路:暴力解是得到两个链表的长度,然后长的链表先多走几步,最后就会同步。这个同步的思想还可以继续优化:采用双指针,你走完了再走别人的,两个指针走的路程都是len(x1)+len(x2)这样最后就可以直接同步到相同节点了。
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode p1=pHead1;
ListNode p2=pHead2;
while(p1!=p2){
if(p1!=null) p1=p1.next;
else p1=pHead2;
if(p2!=null) p2=p2.next;
else p2=pHead1;
}
return p1;
}
}
JZ23 链表中环的入口结点 ⭐⭐
思路:
方法一:找环用快慢指针,快的一次走两步,慢的一次走一步,他俩相等的那个时候可不是入口节点。这个节点还在环内,这时找环的入口节点就是从pHead和相遇节点开始,每次各走一步,这时候相遇的才是环的入口。
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead) {
ListNode pre = pHead;
ListNode p = pre;
while (pre != null && p != null) {
pre = pre.next;
if (p.next == null) return null;
p = p.next.next;
if (pre == p) break;
}
if (p == null || p.next == null) return null;
pre = pHead;
while (p != pre) {
p = p.next;
pre = pre.next;
}
return pre;
}
}
方法二:哈希。使用set,遍历链表;如果set中没有这个节点,就存入这个节点,如果有这个节点,这个节点就是入口节点。
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead) {
Set<ListNode> set =new HashSet<>();
ListNode cur = pHead;
ListNode res = null;
while(cur != null) {
if(set.contains(cur)) {
res = cur;
break;
}
set.add(cur);
cur = cur.next;
}
return res;
}
}
JZ22 链表中倒数最后k个结点 ⭐
思路:
法一:暴力解。
public class Solution {
public ListNode FindKthToTail (ListNode pHead, int k) {
ListNode t=pHead;
int count=0;
while (t != null){
t=t.next;
count++;
}
int m=count-k;
if(m<0) return null;
while(m-->0){
pHead=pHead.next;
}
return pHead;
}
}
法二:双指针,快的先走k步。
public class Solution {
public ListNode FindKthToTail (ListNode pHead, int k) {
ListNode slow, fast;
slow = fast = pHead;
while (k-- != 0) {
if (fast == null) {
return null;
}
fast = fast.next;
}
while (fast != null) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
}