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;
while(cur.next != null && cur.next.next != null){ //待交换的节点不为null
//创建两个临时节点,用于存储改变链表指向后无法访问到的节点的信息
ListNode temp = cur.next;
ListNode temp1 = cur.next.next.next;
cur.next = cur.next.next;
cur.next.next = temp;
temp.next = temp1;
cur = cur.next.next;
}
return dummyHead.next;
}
}
图解:动手画一下,就很好理解了
19.删除链表的倒数第N个节点
题目链接:19.删除链表的倒数第N个节点
题目要求:给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
🤔解题思路
创建虚拟头节点,指向头节点 ,先循环遍历链表得到链表的大小size,再循环遍历得到第size-n个元素,即为待删除结点的前一个元素
💻具体代码
/**
* 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) {
if(head == null){
return head;
}
ListNode temp = head;
int size = 0;
//遍历链表,得到链表的长度
while(temp != null){
size++;
temp = temp.next;
}
ListNode dummyHead = new ListNode(0,head); //创建虚拟头节点,指向头节点
temp = dummyHead;
//遍历链表,得到待删除节点的前一个节点
for(int i = 0;i < size - n;i++){
temp = temp.next;
}
//删除该节点
temp.next = temp.next.next;
return dummyHead.next;
}
}
面试题 02.07. 链表相交
题目链接:面试题 02.07. 链表相交
题目要求:
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
🤔解题思路
💻I.HashSet
利用HashSet不能存入重复元素的规则,依次将两个链表的元素加入到HashSet中,直到找到重复的那个节点,即为相交节点
/**
* 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) {
if(headA == null || headB == null){
return null;
}
ListNode curA = headA;
ListNode curB = headB;
//遍历链表A,将链表A的元素加入到HashSet中
HashSet set = new HashSet();
while(curA != null){
set.add(curA);
curA = curA.next;
}
//遍历链表B,将链表B的元素加入到HashSet中,当加入失败时,此元素为相交节点
while(set.add(curB)){
curB = curB.next;
if(curB == null){
break;
}
}
return curB;
}
}
💻II.双指针
两个指针分别从两个链表的头节点开始遍历,遍历完当前链表后,指针跳到另一个链表继续遍历,直到两个指针指向同一个值,若该值为null,则没有相交节点,若该值为一个节点,则该节点为相交节点。两个指针分别遍历完两个链表时,一定会相等
/**
* 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) {
if(headA == null || headB == null){
return null;
}
ListNode curA = headA;
ListNode curB = headB;
while(curB != curA){
if(curA == null){
curA = headB;
}else{
curA = curA.next;
}
if(curB == null){
curB = headA;
}else{
curB = curB.next;
}
}
return curB;
}
}
图解:
142.环形链表II
题目链接:142.环形链表II
题目要求:
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。不允许修改 链表。
🤔解题思路
💻快慢指针
设置快慢指针,若相遇则有环
/**
* 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) {
if(head == null || head.next == null){
return null;
}
//设置快慢指针
ListNode fast = head;
ListNode slow = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
//如果相遇,则有环
if(fast == slow){
ListNode index1 = head;
ListNode index2 = fast;
while(index1 != index2){
index1 = index1.next;
index2 = index2.next;
}
return index1;
}
}
return null;
}
}
图解:如果还是不理解的,可以看看卡哥的讲解视频 :环形链表 II