1. 移除链表元素-随想录2.
虚拟头节点。
2. 反转链表-随想录3.
3. LC160、相交链表
- 移到剩余长度相等时,再开始比较节点值。
2. 默认A比B长,移动A的指针到B开始的地方。如果遍历出来的长度是B比A长,那么交换A与B。
3. 一旦比较到节点相同,则一定是相交了,不会出现两者相交几个节点之后又岔开的情况,因为节点的next只有一个,所以不可能有一个节点后跟两个next,两者再次岔开。
代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lenA = 0;
int lenB = 0;
//求A长度
ListNode curA = headA;
while(curA != null){
lenA++;
curA = curA.next;
}
//求B长度
ListNode curB = headB;
while(curB != null){
lenB++;
curB = curB.next;
}
//默认A长度大于B,若不是,交换AB
if (lenB > lenA){
int temp = lenA;
lenA = lenB;
lenB = temp;
ListNode tempN = headA;
headA = headB;
headB = tempN;
}
//让A从跟B一样长度的地方开始
int diff = lenA - lenB;
curA = headA;
curB = headB;
while (diff > 0){
curA = curA.next;
diff--;
}
//A剩下的长度和B一样长了,开始逐个遍历并比较节点
while(curA != null){
if (curA == curB){
return curA;
}else{
curA = curA.next;
curB = curB.next;
}
}
return null;
}
}
4. LC141 环形链表
题目链接
快慢指针,快指针一次比慢指针多移动一格。
如果快慢指针相遇,必有环。
注意:while条件:fast也要限制!=null,如果fast=null的话,就没有fast.next了
代码
public class Solution {
public boolean hasCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (slow != null && fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
if (slow == fast){
return true;
}
}
return false;
}
}
5. LC142 环形链表2
和上题的区别是,这题要返回环形入口。
注意区分:相遇节点 和 入口节点
表达式说明了:一个指针从头节点出发,一个指针从相遇节点出发,则两个指针必在入口处碰面。
已知头节点和相遇节点,则题目迎刃而解。
所以解题顺序就是:先找到相遇节点,再找到入口节点。
代码
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
ListNode meet = null;
while(slow != null && fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
if (slow == fast){
meet = slow;
break;
}
}
if (meet == null){
return null;
}
slow = head;
fast = meet;
while (slow != fast){
len++;
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
6. LC21、合并两个有序链表
递归做也可以。
注意这种解法不要忘记==null情况下,让dummy=dummy.next。因为continue后就直接跳出当前循环了,没办法执行循环里最后一句。
代码
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode dummy = new ListNode(-1);
ListNode fix = dummy;
ListNode node1 = list1;
ListNode node2 = list2;
while (node1 != null || node2 != null){
if (node1 == null){
dummy.next = node2;
node2 = node2.next;
dummy = dummy.next;
continue;
}
if (node2 == null){
dummy.next = node1;
node1 = node1.next;
dummy = dummy.next;
continue;
}
if (node1.val > node2.val){
dummy.next = node2;
node2 = node2.next;
}else{
dummy.next = node1;
node1 = node1.next;
}
dummy = dummy.next;
}
return fix.next;
}
}
另一种简洁的:while循环条件不一样。
当有一方为null时,不再循环,cur.next直接为另一方的节点,后续也不用再while遍历,因为另一方的节点的后面连的都是这一方的节点。
private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode sentry = new ListNode(-1);
ListNode curr = sentry;
while(l1 != null && l2 != null) {
if(l1.val < l2.val) {
curr.next = l1;
l1 = l1.next;
} else {
curr.next = l2;
l2 = l2.next;
}
curr = curr.next;
}
if (l1 != null){
curr.next = l1;
}
if (l2 != null){
curr.next = l2;
}
return sentry.next;
}