算法笔记|Day4链表基础II
☆☆☆☆☆leetcode 24. 两两交换链表中的节点
题目分析
1.注意终止条件为cur.next!=null&&cur.next.next!=null,前者为偶数个节点的情况,后者为奇数个节点的情况,而且两个语句的顺序不能改变,以防止cur.next为null导致cur.next.next无法计算;
2.时间复杂度:O(n),空间复杂度:O(1)。
代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummy=new ListNode();
dummy.next=head;
ListNode left,right,temp,cur=dummy;
while(cur.next!=null&&cur.next.next!=null){
left=cur.next;
right=cur.next.next;
temp=cur.next.next.next;
cur.next=right;
right.next=left;
left.next=temp;
cur=cur.next.next;
}
return dummy.next;
}
}
☆☆☆☆☆leetcode 19.删除链表的倒数第N个节点
题目分析
1.采用快慢指针法,slow初始值为dummy,fast初始值为head,并让fast指针先走n步后(注意限制条件fast!=null),slow和fast同时走,以确保fast=null时,slow指向倒数第n个节点的前一个节点,完成删除操作。
2.时间复杂度:O(n),空间复杂度:O(1)。
代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy=new ListNode();
dummy.next=head;
ListNode slow=dummy,fast=head;
while(n>0&&fast!=null){
fast=fast.next;
n--;
}
while(fast!=null){
slow=slow.next;
fast=fast.next;
}
slow.next=slow.next.next;
return dummy.next;
}
}
☆☆☆☆☆leetcode 160. 相交链表
题目链接:leetcode 160. 相交链表
题目分析
1.注意交点不是数值相等,而是指针相等;
2.第一种方法先移动长链对齐尾部,主要步骤为:分别计算两个链表的长度,并将长的链表记作headA,短的链表记作headB(需要交换头结点head和长度len),计算两个链表的长度的差gap,将长链表headA移动gap步与短链表headB对齐,并注意判断结点是否相等,若链表结束无相交元素则返回null;
3.合并链表实现同步移动,分别遍历两个链表,若到达结束,返回到另一个链表的头结点,直至结点相等,若链表结束无相交元素则返回null,示意图见下图;
4.时间复杂度:O(m+n),空间复杂度:O(1)。
代码
1.先行移动长链表实现同步移动
/**
* 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) {
ListNode curA=headA,curB=headB;
int lenA=0,lenB=0;
while(curA!=null){
curA=curA.next;
lenA++;
}
while(curB!=null){
curB=curB.next;
lenB++;
}
if(lenA<lenB){
ListNode temp1=headA;
headA=headB;
headB=temp1;
int temp2=lenA;
lenA=lenB;
lenB=temp2;
}
int gap=lenA-lenB;
while(gap>0){
headA=headA.next;
gap--;
}
while(headA!=null){
if(headA==headB){
return headA;
}
headA=headA.next;
headB=headB.next;
}
return null;
}
}
2.合并链表实现同步移动
/**
* 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) {
ListNode p1=headA,p2=headB;
while(p1!=p2){
p1=p1==null?headB:p1.next;
p2=p2==null?headA:p2.next;
}
return p1;
}
}
☆☆☆☆☆leetcode 142.环形链表II
题目链接:leetcode 142.环形链表II
题目分析
1.此题需要一定数学计算:设头结点到环入口节点的节点数为x,环形入口节点到两指针相遇位置节节点数为y, 从两指针相遇位置到环入口节点节点数为z,slow指针走过节点数为x+y,fast指针走过节点数为x+y+n(y+z)(n为fast指针走过n圈,这里n≥1),为保证fast指针追上slow指针,fast指针每次走2步,slow指针走1步,所以有x+y+n(y+z)=2×(x+y),化简求得x=(n-1)(y-z)+z,也就是从头结点和相遇位置,各走一步,直到相遇,相遇点即为环入口(n≥2时,从相遇位置走的节点会走过(n-1)圈);
2.时间复杂度:O(n),空间复杂度:O(1)。
代码
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow=head,fast=head;
while(fast!=null&&fast.next!=null){
slow=slow.next;
fast=fast.next.next;
if(slow==fast){
ListNode index1=fast,index2=head;
while(index1!=index2){
index1=index1.next;
index2=index2.next;
}
return index1;
}
}
return null;
}
}