-
环形链表 II(142. Linked List Cycle II)
问题描述:给定一个链表,返回链表开始入环的第一个节点。如果链表无环,则返回null。
解决方案:
//142.环形链表II
public ListNode detectCycle(ListNode head) {
///耗时较长
Setset = new HashSet<>(); /
ListNode cur = head;
while (cur != null) {
if (set.contains(cur)) {
return cur;
}
set.add(cur);
cur = cur.next;
}
return null;
ListNode slow = head;
ListNode fast = head;
boolean isCycle = false;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
isCycle=true;
break;
}
}
//从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点,
// 那么当这两个指针相遇的时候就是 环形入口的节点。
if (isCycle) {
slow = head;
while (fast != slow) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
return null;
}
解释:
使用快慢指针法检测环的存在。
如果检测到环,将一个指针重置为链表的头节点,然后两个指针同时向前移动,每次移动一步,当两个指针再次相遇时,该点即为环的入口。 -
面试题 02.07. 链表相交
问题描述:给定两个单链表,判断它们是否相交,如果相交,返回相交的起始节点。
解决方案:
//面试题 02.07. 链表相交
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) {
return null;
}
ListNode a=headA,b=headB;
int aLen=0,bLen=0;
while (a != null) {
aLen++;
a=a.next;
}
while (b != null) {
bLen++;
b=b.next;
}
a=headA;
b=headB;
int diff=Math.abs(aLen-bLen);
if(aLen>bLen){
//int diff=aLen-bLen;
for(int i=0;i<diff;i++){
a=a.next;
}
while(a!=null){
if(ab){
return a;
}
a=a.next;
b=b.next;
}
}else {
//int diff=bLen-aLen;
for(int i=0;i<diff;i++){
b=b.next;
}
while(b!=null){
if(ba){
return b;
}
b=b.next;
a=a.next;
}
}
return null;
}
/(版本二) 合并链表实现同步移动
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
// p1 指向 A 链表头结点,p2 指向 B 链表头结点
ListNode p1 = headA, p2 = headB;
while (p1 != p2) {
// p1 走一步,如果走到 A 链表末尾,转到 B 链表
if (p1 == null) p1 = headB;
else p1 = p1.next;
// p2 走一步,如果走到 B 链表末尾,转到 A 链表
if (p2 == null) p2 = headA;
else p2 = p2.next;
}
return p1;
}
}/
解释:
计算两个链表的长度。
将较长的链表的指针移动到与较短链表相同长度的位置。
同时移动两个指针,如果相遇则返回该节点,否则返回null。 -
删除链表的倒数第N个节点(19. Remove Nth Node From End of List)
问题描述:给定一个链表,删除链表的倒数第n个节点,并返回新的链表头节点。
解决方案:
// 19.删除链表的倒数第N个节点
public ListNode removeNthFromEnd(ListNode head, int n) {
int size = 0;
ListNode dummy = new ListNode(Integer.MIN_VALUE,head);
ListNode cur = dummy.next;
while (cur!= null) {
size++;
cur = cur.next;
}
if (size == n) {
return head.next;
}
cur=dummy;
for (int i = 0; i < size - n; i++) {
if (cur != null) {
cur = cur.next;
}
}
if (cur!=null&&cur.next != null) {
cur.next=cur.next.next;
}
return dummy.next;
}
解释:
使用一个哨兵节点dummy,其next指针指向链表的头节点。
计算链表的长度size。
如果要删除的节点是头节点,直接返回head.next。
否则,找到倒数第n+1个节点,将其next指针指向倒数第n-1个节点,从而删除倒数第n个节点。 -
两两交换链表中的节点(24. Swap Nodes in Pairs)
问题描述:给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
解决方案:
//24. 两两交换链表中的节点
public ListNode swapPairs(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode cur1=head;
ListNode cur2=head.next;
ListNode res=cur2;
ListNode temp;
while (true){
temp=cur2.next;
cur1.next=temp;
cur2.next=cur1;
if(tempnull){
break;
} else if (temp.nextnull) {
break;
}else {
cur1.next=temp.next;
}
cur1=temp;
cur2=temp.next;
}
return res;
}
解释:
如果链表为空或只有一个节点,直接返回原链表。
使用两个指针cur1和cur2分别指向当前节点和下一个节点。
交换两个节点,并更新指针。
重复上述步骤,直到链表结束。