leetcode 24
题目链接
交换两两节点
思路:
- 设置虚拟头结点
dummy
- 设置一个指针
cur
始终指向要交换的两个节点的前一个节点 - 注意遍历终止——奇数个节点和偶数个节点情况
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummy = new ListNode(-1, head);
ListNode cur = dummy;
ListNode p, q;
while (cur.next != null) {
p = cur.next;
q = cur.next.next;
if (q == null) //落单的元素,不用交换
break;
cur.next = q;
p.next = q.next;
q.next = p;
cur = p; //修改cur指向下一个要交换的
}
return dummy.next;
}
}
leetcode 19
题目链接
**重点:**找到倒数第N个节点
思路:
- 快慢指针
- 慢指针
slow
最终指向要删除的前一个结点 - 快指针
fast
先提前走N步,让快慢指针之间差N个节点 - 然后同时移动,直到
fast
走到头
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(-1, head);
ListNode cur = dummy;
ListNode target = cur;
for (int i = 0; i <= n; ++i)
target = target.next;
while (target != null) {
cur = cur.next;
target = target.next;
}
cur.next = cur.next.next;
return dummy.next;
}
}
面试题02.07
题目链接
找到两个链表相交(即相同)的元素节点
思路:
- 双指针
- 注意双指针不是同时向后移动的
- 因为是后面相交,所以先找到与短的那个链表同的长度
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode p = headA;
ListNode q = headB;
int aLen = 0, bLen = 0;
while (p != null) { //get len
++aLen;
p = p.next;
}
while (q != null) {
++bLen;
q = q.next;
}
p = headA;
q = headB;
if (aLen > bLen) {
for (int i = 0; i < aLen - bLen; ++i)
p = p.next;
while (p != null) {
if (p == q)
return p;
p = p.next;
q = q.next;
}
return null;
}
else {
for (int i = 0; i < bLen - aLen; ++i)
q = q.next;
while (q != null) {
if (p == q)
return p;
p = p.next;
q = q.next;
}
return null;
}
}
}
leetcode 142
思路:
- 判断是否有环——快慢指针
- 找到环的入口
快慢指针
fast
每次移动2步、slow
每次移动1步- 两者相遇——有环
找环的入口
- 快慢指针相遇节点&
head
,两者同时往后
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast = head, slow =head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) { //有环
ListNode p = fast;
ListNode q = head;
while (p != q) {
p = p.next;
q = q.next;
}
return p;
}
}
return null;
}
}