24.两两交换链表中的节点
- 24.两两交换链表中的节点 | 题目链接
- 题目描述:给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
- 思路:能力不行 一定要画图!!!
/**
* 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 dummyHead = new ListNode(0, head);
ListNode cur = dummyHead;
ListNode temp;
ListNode temp1;
ListNode temp2;
while(cur.next != null && cur.next.next != null) {
temp = cur.next.next.next;
temp1 = cur.next;
temp2 = cur.next.next;
cur.next = temp2;
temp2.next = temp1;
temp1.next = temp;
cur = temp1;
}
return dummyHead.next;
}
}
19.删除链表的倒数第N个节点
-
题目描述:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5] 示例 2: 输入:head = [1], n = 1 输出:[] 示例 3: 输入:head = [1,2], n = 1 输出:[1]
-
思路:推荐使用虚拟头结点,这样方便处理删除实际头结点的逻辑。
- 定义fast指针和slow指针,初始值为虚拟头结点,如图:
- fast首先走n + 1步 ,为什么是n+1呢,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作),如图:
- fast和slow同时移动,直到fast指向末尾,如题:
- 删除slow指向的下一个节点,如图:
- 定义fast指针和slow指针,初始值为虚拟头结点,如图:
/**
* 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 dummyHead = new ListNode(0, head);
ListNode fast = dummyHead;
ListNode slow = dummyHead;
/** fast先走n+1步 */
for(int i = 0; i <= n; i++) {
fast = fast.next;
}
//fast多走一步,slow少走一步,此时指向倒数第N个的前一个。
while(fast != null) {
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummyHead.next;
}
}
面试题02.07.链表相交
- 02.07.链表相交 | 题目链接
- 题目描述:给两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null
- 思路:
-
简单来说,就是求两个链表交点节点的指针。 这里要注意,交点不是数值相等,而是指针相等。
-
为了方便举例,假设节点元素数值相等,则节点指针相等。
-
看如下两个链表,目前curA指向链表A的头结点,curB指向链表B的头结点:
-
我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置,如图:
-
此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。否则循环退出返回空指针。
-
/**
* 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;
ListNode curB = headB;
int lenA = 0, lenB = 0;
//得到链表A/B的长度。
while(curA != null) {
lenA++;
curA = curA.next;
}
while(curB != null) {
lenB++;
curB = curB.next;
}
curA = headA;
curB = headB;
//定义A变为长链表,如果B为长链表则通过if操作把A交换成为长链表。
if(lenB > lenA) {
int templenA = lenA;
lenA = lenB;
lenB = templenA;
ListNode tempcurA = curA;
curA = curB;
curB = tempcurA;
}
//计算链表A/B的长度差值,计算出长链表的头节点应该往后移多少。
int gap = lenA - lenB;
//移动长链表A的头节点,使链表A/B的尾巴对齐。
while(gap-- > 0) {
curA = curA.next;
}
//此时判断两个链表是否相交。
while(curA != null) {
if(curA == curB) {
return curA;
}
curA = curA.next;
curB = curB.next;
}
return null;
}
}
环形链表Ⅱ
- 142.环形链表 | 题目链接
- 题目描述: 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
- 思路
看大佬讲吧:大佬讲解链接
/**
* 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 fast = head;
ListNode slow = head;
while(fast != null && fast.next != null) { //判断fast不能为空,因为fast是两步两步走的,所以要判断fast本身和它的下一个节点不为空。如果这个满足了,那就说明没有环,返回null。
fast = fast.next.next;
slow = slow.next;
if(fast == slow) { //有环
ListNode index = head;
//slow走x+y;fast走x+y+n(y+z); x是入环的长度,y+z是环一圈的长度。
//2(x+y)=x+y+n(y+z);
//x=(n-1)(y+z)+z; n=1时,x=z;
while(index != fast) {
index = index.next;
fast = fast.next;
}
return index;
}
}
return null;
}
}