24. 两两交换链表中的节点
题目链接:24. 两两交换链表中的节点 - 力扣(LeetCode)
代码实现了题目解析:代码随想录两两交换链表中的节点
题目描述:
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例 :
具体代码实现:
//两两交换链表中的节点
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 dumyhead = new ListNode();
dumyhead.next = head;
ListNode cur = dumyhead;
while (cur.next != null && cur.next.next != 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 dumyhead.next ;
}
}
public class Solution_text {
public static void main(String[] args){
ListNode head = new ListNode (Integer.parseInt(args[0]));
ListNode cur = new ListNode();
cur = head; //保留头指针,创建副本来遍历
for(int i=1 ; i<args.length ; i++){ //从主函数中传入参数创建列表
cur.next = new ListNode (Integer.parseInt(args[i]));
cur = cur.next;
}
// 打印原始链表
System.out.println("原始链表:");
printLinkedList(head);
Solution solution = new Solution();
// 调用 swapPairs 方法交换节点
ListNode modifiedListhead = solution.swapPairs(head);
// 打印修改后的链表
System.out.println("修改后的链表:");
printLinkedList(modifiedListhead);
}
//打印链表
private static void printLinkedList(ListNode head1) {
ListNode current = head1;
while (current != null) {
System.out.print(current.val + " ");
current = current.next;
}
System.out.println();
}
}
19.删除链表的倒数第N个节点
代码实现了题目解析:代码随想录删除链表的倒数第N个节点
题目描述:
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
示例 :
具体代码实现:
//删除列表倒数第n个元素
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 dumyhead = new ListNode();
dumyhead.next = head;
ListNode fast = dumyhead;
ListNode slow = dumyhead;
n = n+1; //目的是让快指针多走一步,等快指针到达末尾空指针时,
//慢指针刚好到达待删除指针的前一位,便于进行删除操作
while( n-- !=0 && fast != null)
fast = fast.next;
while(fast != null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next ;
return dumyhead.next ;
}
}
public class Solution_text {
public static void main(String[] args){
ListNode head = new ListNode (Integer.parseInt(args[0]));
ListNode cur = new ListNode();
cur = head; //保留头指针,创建副本来遍历
for(int i=1 ; i<args.length-1 ; i++){ //从主函数中传入参数创建列表
cur.next = new ListNode (Integer.parseInt(args[i]));
cur = cur.next;
}
// 打印原始链表
System.out.println("原始链表:");
printLinkedList(head);
int val = Integer.parseInt(args[args.length-1]); //确定待删除元素
System.out.println("删除链表的倒数第" + val + "个元素");
Solution solution = new Solution();
// 调用 removeElements 方法删除节点
ListNode modifiedListhead = solution.removeNthFromEnd(head,val);
// 打印修改后的链表
System.out.println("修改后的链表:");
printLinkedList(modifiedListhead);
}
//打印链表
private static void printLinkedList(ListNode head1) {
ListNode current = head1;
while (current != null) {
System.out.print(current.val + " ");
current = current.next;
}
System.out.println();
}
}
面试题 02.07. 链表相交
题目链接:面试题 02.07. 链表相交 - 力扣(LeetCode)
代码实现了题目解析:代码随想录面试题 02.07. 链表相交
题目描述:
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null
。
图示两个链表在节点 c1
开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
具体代码实现:
//找出并返回两个单链表相交的起始节点
import java.util.Scanner;
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 getIntersectionNode(ListNode headA, ListNode headB) {
ListNode curA = headA;
ListNode curB = headB;
int lenA = 0, lenB = 0;
while (curA != null) { // 求链表A的长度
lenA++;
curA = curA.next;
}
while (curB != null) { // 求链表B的长度
lenB++;
curB = curB.next;
}
curA = headA;
curB = headB;
// 让curA为最长链表的头,lenA为其长度
if (lenB > lenA) {
//1. swap (lenA, lenB);
int tmpLen = lenA;
lenA = lenB;
lenB = tmpLen;
//2. swap (curA, curB);
ListNode tmpNode = curA;
curA = curB;
curB = tmpNode;
}
// 求长度差
int gap = lenA - lenB;
// 让curA和curB在同一起点上(末尾位置对齐)
while (gap-- > 0) {
curA = curA.next;
}
// 遍历curA 和 curB,遇到相同则直接返回
while (curA != null) {
if (curA == curB) {
return curA;
}
curA = curA.next;
curB = curB.next;
}
return null;
}
}
public class Solution_text {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入第一个链表(以空格分隔节点值):");
ListNode head1 = readLinkedList(scanner.nextLine().trim());
System.out.println("请输入第二个链表(以空格分隔节点值):");
ListNode head2 = readLinkedList(scanner.nextLine().trim());
// 打印原始链表
System.out.println("两个链表:");
printLinkedList(head1);
printLinkedList(head2);
int len1 = 0, len2 = 0;
ListNode cur1 = head1;
ListNode cur2 = head2;
while (cur1 != null) { // 求链表A的长度
len1++;
cur1 = cur1.next;
}
while (cur2 != null) { // 求链表B的长度
len2++;
cur2 = cur2.next;
}
if(len1 >= len2)
head1 = head2 ;
else
head2 = head1 ; //必须将两个链表相连才会有交点
Solution solution = new Solution();
// 调用 getIntersectionNode 方法获取重合的首节点
ListNode intersectionNode = solution.getIntersectionNode(head1, head2);
if (intersectionNode != null) {
System.out.println("重合的首节点:" + intersectionNode.val); //节点相交是同一个节点 不是同一个val值
} else {
System.out.println("链表没有相交的节点。");
}
}
// 读取链表
private static ListNode readLinkedList(String line) {
String[] values = line.split(" ");
ListNode dummy = new ListNode();
ListNode curr = dummy;
for (String value : values) {
curr.next = new ListNode(Integer.parseInt(value));
curr = curr.next;
}
return dummy.next;
}
// 打印链表
private static void printLinkedList(ListNode head) {
ListNode current = head;
while (current != null) {
System.out.print(current.val + " ");
current = current.next;
}
System.out.println();
}
}
142.环形链表II
题目链接:142. 环形链表 II - 力扣(LeetCode)
代码实现了题目解析:代码随想录环形链表II
题目描述:
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
示例 :
具体代码实现:
//环形链表||
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 detectCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null){
fast = fast.next.next; //快指针一次走两步,只比慢指针多走一步,防止在追赶慢指针时,跳过了慢指针而没相遇
slow = slow.next ; //慢指针一次走一步
if(slow == fast){ //当两指针相遇时
ListNode index1 = fast;
ListNode index2 = head;
// 两个指针,从头结点和相遇结点,各走一步,直到相遇,相遇点即为环入口
//为什么相遇点即为环入口? ,假设从头结点到环入口为x,环入口到相遇位置为y,剩余位置(即相遇位置到入口为Z)
//假设在快指针走过一圈循环(圈数不影响结论)就撵上慢指针时,2(x+y)= x+y+z+y ===> x=z
while(index1 != index2){
index1 = index1.next ;
index2 = index2.next ;
}
return index1; //
}
}
return null;
}
}
public class Solution_text {
public static void main(String[] args){
ListNode head = new ListNode (Integer.parseInt(args[0]));
ListNode cur = new ListNode();
cur = head; //保留头指针,创建副本来遍历
for(int i=1 ; i<args.length-1 ; i++){ //从主函数中传入参数创建列表
cur.next = new ListNode (Integer.parseInt(args[i]));
cur = cur.next;
if(i == args.length-2){
cur.next = new ListNode (Integer.parseInt(args[i+1]));
cur = cur.next;
cur.next = head.next; //假设把结尾的next(即null)指向第二个指针,形成环
} //所以结果肯定为第二个节点的值
}
Solution solution = new Solution();
ListNode modifiedListhead = solution.detectCycle(head);
// 打印修改后的链表
System.out.println("环的入口:" + modifiedListhead.val);
}
}