代码随想录day04

本文详细解析了四个经典的链表算法题目:两两交换链表中的节点、删除链表的倒数第N个节点、链表相交及环形链表II。提供了包括设置虚拟头结点、双指针等技巧在内的多种解决方案。

一、两两交换链表中的节点(LeetCode24)

设置虚拟头结点

/**
 * 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(-1,head); //设置虚拟头结点
        dummyHead.next = head;
        ListNode currentHead = dummyHead; //设置临时指针节点
        ListNode tem = null,tem1 = null; //设置临时保存节点
        while(currentHead.next!=null&&currentHead.next.next!=null){
            tem = currentHead.next;
            tem1 = currentHead.next.next.next;
            currentHead.next = currentHead.next.next;
            currentHead.next.next = tem;
            tem.next = tem1;
            currentHead = currentHead.next.next; //相邻两个节点交换位置后,指针后移两位
        }
        return dummyHead.next;
    }
}

递归

/**
 * 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) {
        if(head == null || head.next == null){
            return head;
        }
        ListNode next = head.next; //获取当前节点的下一个节点
        ListNode newNode = swapPairs(next.next); //进行递归
        //进行交换
        next.next = head;
        head.next = newNode;
        return next;
    }
}

二、删除链表的倒数第N个节点(LeetCode19)

双指针

/**
 * 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(-1,head);
        ListNode fast = dummyHead;
        ListNode slow = dummyHead;
        //快慢指针相差n+1个节点
        n++;
        while(n-- > 0){
            fast = fast.next;    
        }
        while(fast != null){
            fast = fast.next;
            slow = slow.next;
        }
        slow.next = slow.next.next;
        return dummyHead.next;
    }
}

三、链表相交(面试题 02.07)

设置双指针,链表尾端对齐后判断值相等

/**
 * 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 currentA = headA;
        ListNode currentB = headB;
        int lengthA = 0, lengthB = 0;
        while (currentA != null) { // 求链表A的长度
            lengthA++;
            currentA = currentA.next;
        }
        while (currentB != null) { // 求链表B的长度
            lengthB++;
            currentB = currentB.next;
        }
        //让当前指针重新回到头结点
        currentA = headA;
        currentB = headB;
        //使其A为长链表
        if(lengthA < lengthB){
            //长度交换
            int temLength = lengthA;
            lengthA = lengthB;
            lengthB = temLength;
            //链表交换
            ListNode newlist = currentA;
            currentA = currentB;
            currentB = newlist;
        }
        //末尾对齐,长链表当前指针移动与短链表指针对齐
        for(int i = 0;i < lengthA - lengthB;i++){
            currentA = currentA.next;
        }
        //循环找出公共点
        while(currentA != null){
            if(currentA == currentB){
                return currentA;
            }
            currentA = currentA.next;
            currentB = currentB.next;
        }
        return null;
    }
}

四、环形链表II(LeetCode142)

双指针,判断环后再次设置双指针相遇即为入口

/**
 * 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.next.next;
            slow = slow.next;
            if(fast == slow){ //有环
                ListNode index1 = fast;
                ListNode index2 = head;
                // 两个指针,从头结点和相遇结点,各走一步,直到相遇,相遇点即为环入口
                while(index1 != index2){
                    index1 = index1.next;
                    index2 = index2.next;
                }
                return index1;
            }
        }
        return null;
    }
}
### 关于代码随想录 Day04 的学习资料与解析 #### 一、Day04 主要内容概述 代码随想录 Day04 的主要内容围绕 **二叉树的遍历** 展开,包括前序、中序和后序三种遍历方式。这些遍历可以通过递归实现,也可以通过栈的方式进行迭代实现[^1]。 #### 二、二叉树的遍历方法详解 ##### 1. 前序遍历(Pre-order Traversal) 前序遍历遵循访问顺序:根节点 -> 左子树 -> 右子树。以下是基于递归的实现: ```python def preorderTraversal(root): result = [] def traversal(node): if not node: return result.append(node.val) # 访问根节点 traversal(node.left) # 遍历左子树 traversal(node.right) # 遍历右子树 traversal(root) return result ``` 对于迭代版本,则可以利用显式的栈来模拟递归过程: ```python def preorderTraversal_iterative(root): stack, result = [], [] current = root while stack or current: while current: result.append(current.val) # 访问当前节点 stack.append(current) # 将当前节点压入栈 current = current.left # 转向左子树 current = stack.pop() # 弹出栈顶元素 current = current.right # 转向右子树 return result ``` ##### 2. 中序遍历(In-order Traversal) 中序遍历遵循访问顺序:左子树 -> 根节点 -> 右子树。递归实现如下: ```python def inorderTraversal(root): result = [] def traversal(node): if not node: return traversal(node.left) # 遍历左子树 result.append(node.val) # 访问根节点 traversal(node.right) # 遍历右子树 traversal(root) return result ``` 迭代版本同样依赖栈结构: ```python def inorderTraversal_iterative(root): stack, result = [], [] current = root while stack or current: while current: stack.append(current) # 当前节点压入栈 current = current.left # 转向左子树 current = stack.pop() # 弹出栈顶元素 result.append(current.val) # 访问当前节点 current = current.right # 转向右子树 return result ``` ##### 3. 后序遍历(Post-order Traversal) 后序遍历遵循访问顺序:左子树 -> 右子树 -> 根节点。递归实现较为直观: ```python def postorderTraversal(root): result = [] def traversal(node): if not node: return traversal(node.left) # 遍历左子树 traversal(node.right) # 遍历右子树 result.append(node.val) # 访问根节点 traversal(root) return result ``` 而迭代版本则稍复杂一些,通常采用双栈法或标记法完成: ```python def postorderTraversal_iterative(root): if not root: return [] stack, result = [root], [] while stack: current = stack.pop() result.insert(0, current.val) # 插入到结果列表头部 if current.left: stack.append(current.left) # 先压左子树 if current.right: stack.append(current.right) # 再压右子树 return result ``` #### 三、补充知识点 除了上述基本的二叉树遍历外,Day04 还可能涉及其他相关内容,例如卡特兰数的应用场景以及组合问题的基础模板[^2][^4]。如果遇到具体题目,可以根据实际需求调用相应算法工具。 --- ####
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值