day-4
19.删除倒数第K个节点
在链表算法题中,加入虚拟头节点(dummy node)的主要目的是简化链表的操作。虚拟头节点是一个不存储实际数据的节点,它仅用于指向链表的第一个真正的节点。使用虚拟头节点可以避免对第一个真正节点进行特殊处理,从而使代码更加简洁。
例如,当我们需要在链表中删除一个特定节点时,我们需要找到该节点的前一个节点来修改其指针,但是如果该节点是链表的头节点,就需要特殊处理,这会导致代码逻辑复杂。而如果加入了虚拟头节点,那么遍历链表时就可以始终从虚拟头节点的下一个节点开始,从而避免了特殊处理头节点的问题。
此外,加入虚拟头节点还可以避免空链表(即链表中没有节点的情况)的特判处理。因为虚拟头节点的存在,头节点和其他节点都是按照同样的方式进行处理的,这简化了代码的编写和阅读。
https://leetcode.cn/problems/remove-nth-node-from-end-of-list/
虚拟节点
删除倒数第K个,那么就要找到倒数第K+1个,然后K+1.next=k+1.next.nxet
就把第K个给删了
package com.example.leetcode.labuladong.sxl.sxl_4;
public class sxl_19 {
class ListNode{
int val;
ListNode next;
ListNode(){
}
ListNode(int val){
this.val = val;
}
ListNode(int val,ListNode next){
this.val = val;
this.next = next;
}
}
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode x = findFromEnd(dummy, n + 1);
x.next = x.next.next;
return dummy.next;
}
ListNode findFromEnd(ListNode head, int k) {
ListNode p1 = head;
for (int i = 0; i < k; i++) {
p1 = p1.next;
}
ListNode p2 = head;
while (p1 != null) {
p2 = p2.next;
p1 = p1.next;
}
return p2;
}
}
24.两两交换
两两交换链表中的值
https://leetcode.cn/problems/swap-nodes-in-pairs/
1、先进性判断,当前链表是否满足两两交换的条件:条件就是至少有2个节点
2、满足的话,我们就先交换前面2个,然后后面的再走递归获取
package com.example.leetcode.labuladong.sxl.sxl_4;
public class sxl_24 {
class ListNode {
int val;
ListNode next;
ListNode() {
}
ListNode(int val) {
this.val = val;
}
ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
public ListNode swapPairs(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode first = head;
ListNode second = head.next;
ListNode others = head.next.next;
second.next = first;
first.next = swapPairs(others);
return second;
}
}
142.环形链表2
/**
* 判断是否是环形链表,以及如果是,判断一下起始节点
*/
快慢指针,快是2倍数走,慢是1倍数走,等到2者相遇,慢从头走,快1倍数走,再次相遇,就是环起始点
package com.example.leetcode.labuladong.sxl.sxl_4;
public class sxl_142 {
class ListNode{
int val;
ListNode next;
ListNode(){
}
ListNode(int val){
this.val = val;
}
ListNode(int val,ListNode next){
this.val = val;
this.next = next;
}
}
public ListNode detectCycle(ListNode head) {
ListNode fast, slow;
fast = slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if (fast == slow) break;
}
if (fast == null || fast.next == null) {
return null;
}
slow = head;
while (slow != fast) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
160.判断链表是否相交
/**
* 判断链表是否相交
*
* https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/
*/
个人很喜欢的一种写法,二者同时遍历,相等就退出(退出时要么都是null,要么就是相交的点)
package com.example.leetcode.labuladong.sxl.sxl_4;
public class sxl_160 {
class ListNode{
int val;
ListNode next;
ListNode(){
}
ListNode(int val){
this.val = val;
}
ListNode(int val,ListNode next){
this.val = val;
this.next = next;
}
}
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode p = headA;
ListNode q = headB;
while (p!=q){
if(p==null){
p=headB;
}else{
p=p.next;
}
if(q==null){
q=headA;
}else{
q=q.next;
}
}
return p;
}
}