代码随想录刷题笔记(DAY4)
今日总结:今天把中心放在前端学习上,最后一个题没有完全理解,明天早起补上吧。勉强算完成任务。
Day 4
01. 两两交换链表中的节点(No. 24)
1.1 题目
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例 1:

输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例 2:
输入:head = []
输出:[]
示例 3:
输入:head = [1]
输出:[1]
1.2 笔记
先来分析需不需要虚拟头节点,虚拟头节点是为了让处理头节点的方式和处理其他节点的方式相同,不用再单独写出来,所以先考虑头节点和其他节点的处理方式是否一样:
交换一个中间的节点需要哪些操作呢?

需要将前一个节点,也就是上图第一个点指向第三个点,但是头节点并没有前一个节点,所以我们得出头节点和其他节点的处理方式是不同的,所以引入虚拟头节点。(上图是要进行的操作,标号不代表顺序)
也很容易能看出,要交换两个节点需要前一个节点和后一个节点,所以我们的 cur 要定义在前一个节点:

这里我们先给上个图加上序号
- 先让 cur指向它的下下个节点(3 节点),但这时我们发现cur的下一个节点(2 节点)是不可达的,定义temp1指向这个节点

- 使得 temp1(节点 2 )的下一个节点指向 (节点 4)

- 让 (节点 3)再指向 (节点2)这样拉直后就实现了反转

接下来我们来看循环遍历的出口,如果是偶数个元素的话我们要保证 cur 后面有一个元素(有一个元素就代表后面还有一组元素,还需要循环交换),奇数个元素的话则需要保证 cur 的后面有两个个元素就结束(有两个元素才需要交换,一个的话不需要交换直接结束),先尝试写出循环遍历的出口
while(cur.next.next != null)
while(cur.next != null)
很明显看出这两个是包含关系,则可以写出
while(cur.next != null && cur.next.next != null)
1.3 代码
/**
 * 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;
        ListNode temp1; // 临时节点
        ListNode temp2;
        while (cur.next != null && cur.next.next != null) {
            temp1 = cur.next;
            cur.next = cur.next.next;
            temp1.next = cur.next.next;
            cur.next.next = temp1;
            cur = cur.next.next;
        }
        return dummyHead.next;
    }
}
02. 删除链表的倒数第 N 个结点(No. 19)
1.1 题目
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例 1:

输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例 2:
输入:head = []
输出:[]
示例 3:
输入:head = [1]
输出:[1]
1.2 笔记
这道题的关键是如何找到删除节点的前一个节点,然后我们只需要让 node.next = node.next.next 就完成了删除操作,下面来思考如何找到这个节点呢?
因为题目里面给的是倒数第 N 个节点,所以很容易想到倒序遍历链表,回顾一下如何倒序遍历链表呢?
public void backtracking(ListNode head) {
	if (head.next == null) {
        // 到了最后一个节点
        return head;
    }
    ListNode node = head; // 记录当前栈中的 head
    backtracking(head.next);
    System.sout.println(node); // 实现倒叙输出
}
这道题的思路就变得清晰起来了,递归遍历到最后一个节点然后我们开始计数,直到倒数第 N 个节点的前一个节点,就比如 1 的话需要在倒数第二个栈执行操作,可以写出
        if (--N == 0) {
            // 要删除的节点的前一个节点
            node.next = node.next.next;
            return;
        }
下面给出完整的代码
1.3 代码
/**
 * 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 {
    int N = 0;
    ListNode dummyNode = new ListNode();
    public ListNode removeNthFromEnd(ListNode head, int n) {
        N = n;
        dummyNode.next = head;
        backtracking(dummyNode);
        return dummyNode.next;
    }
    public void backtracking(ListNode head) {
        if (head.next == null) {
            // 最后一个节点
            return;
        }
        backtracking(head.next);// 递归遍历节点
        ListNode node = head;
        if (--N == 0) {
            // 要删除的节点的前一个节点
            node.next = node.next.next;
            return;
        }
        return;
    }
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!