代码随想录算法训练营第四天

LeetCode.24 两两交换链表中的节点

题目链接 两两交换链表中的节点

题解一、递归法

class Solution {
    public ListNode swapPairs(ListNode head) {
        if(head == null || head.next == null){
            return head;
        }
        ListNode nextNode = head.next;
        ListNode newNode = swapPairs(nextNode.next);
        nextNode.next = head;
        head.next = newNode;
        return nextNode;
    }
}

解题思路

newNode可以视为后面以及排序好后的链表的头节点,即样例1->2->3->4,newNode是节点2后面的链表的头节点,然后对head(1),nextNode(2),newNode(2后面的链表头节点),对这三个节点进行重新排序。

题解二、循环迭代法

class Solution {
    public ListNode swapPairs(ListNode head) {
        if(head == null || head.next == null){
            return head;
        }
        ListNode dummyNode = new ListNode(0);
        dummyNode.next = head;
        ListNode curNode = dummyNode;
        while(curNode.next != null && curNode.next.next != null){
            ListNode tmpNode = curNode.next.next;
            curNode.next.next = tmpNode.next;
            tmpNode.next = curNode.next;
            curNode.next = tmpNode;
            curNode = curNode.next.next;
        }
        return dummyNode.next;
    }
}

解题思路

由于可能会操作到头节点,即头节点也可能被交换顺序,这里使用虚拟头节点。首先头节点以及头节点的下一个指针进行特判,然后进行循环遍历,每次循环两个节点就对这两个节点进行交换处理,交换之后将指针向右移动两个位置。如果最后长度小于2,直接返回当前指针,此时循环也到此结束。

LeetCode.19 删除链表的倒数第K个节点

题目链接 删除链表的倒数第K个节点

题解一、快慢指针法

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummyNode = new ListNode(0);
        dummyNode.next = head;
        ListNode firstIndex = dummyNode;
        ListNode secondIndex = dummyNode;
        for(int i = 0;i<=n;i++){
            firstIndex = firstIndex.next;
        }    
        while(firstIndex != null){
            firstIndex = firstIndex.next;
            secondIndex = secondIndex.next;
        }
        if(secondIndex.next!=null){
            secondIndex.next = secondIndex.next.next;
        }
        return dummyNode.next;
    }
}

解题思路

快慢指针法,让快指针先走n + 1步,然后慢指针再开始走,快慢指针始终相差n + 1个节点,当快指针到链表底部,对慢指针的下一个节点进行删除操作,即slowIndex.next = slowIndex.next.next;

题解二、递归法

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        // 由于可能头节点也可能是被删除的对象,所以设置一个虚拟头节点
        ListNode dummyNode = new ListNode(0);
        dummyNode.next = head;
        removeN(dummyNode,n);
        return dummyNode.next;
    }
    public int removeN(ListNode head,int n){
        // n 是计数器,代表倒数第几个节点
        if(head == null){
            // 链表到底了,返回0
            return 0;
        }
        int curN = removeN(head.next,n);
        if(curN == n){
            // 进行删除操作
            head.next = head.next.next;
        }
        return curN + 1;
    }
}

递归实现,利用递归的回溯来计算这是倒数第几个节点,详情可以看代码的注解。

LeetCode 面试题02.07.链表相交

题目链接 面试题02.07.链表相交

题解

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode p1 = headA;
        ListNode p2 = headB;
        while(p1 != p2){
            if(p1 != null){
                p1 = p1.next;
            }else {
                p1 = headB;
            }
            if(p2 != null){
                p2 = p2.next;
            }else {
                p2 = headA;
            }
        }
        return p1;
    }
}

解题思路

假设A链表和B链表不相交,那么两个下标p1,p2必定是分别从自己链表到对方链表各移动一遍,移动的长度是m + n,然后同时到达对方的尾节点,同时为null ,这个时候退出循环,返回p1 为 null符合题意,否则必定会在移动长度小于 m + n之内相遇。

LeetCode.142 环形链表Ⅱ

题目链接 环形链表Ⅱ

题解

public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head == null || head.next == null){
            return null;
        }
        ListNode fastIndex = head;
        ListNode slowIndex = head;
        while(fastIndex!= null && fastIndex.next != null){
            fastIndex = fastIndex.next.next;
            slowIndex = slowIndex.next;
            if(slowIndex == fastIndex){
                ListNode a = fastIndex;
                ListNode b = head;
                while(a != b){
                    a = a.next;
                    b = b.next;
                }
                return a;
            }
        }
        return null;
    }
}

解题思路

快慢指针,如果有环的话,可以视为快指针绕了一圈环,然后快指针追着慢指针,最终在环中相遇,找环的出口可以看一下卡尔的解题思路与证明

收获与总结

收获了链表快慢指针的写法,递归的写法,对这些写法掌握得更深,比如想获得链表的中间,可以快慢指针从头开始同时进行遍历,快指针移动两位,慢指针移动一位,当快指针到终点时,慢指针就刚好到中间位置等等用法,后续继续加油。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值