IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【LeetCode】关于链表的删除 -> 正文阅读

[数据结构与算法]【LeetCode】关于链表的删除


237. 删除链表中的节点

因为在单链表中,无法直接得到一个节点的前驱,因此本题删除的时候,可以进行“移花接木”:

  • 将node后继节点的值赋给node;
  • 然后删除node的后继节点。
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public void deleteNode(ListNode node) {
        node.val = node.next.val; // 将node后继节点的值赋给node
        node.next = node.next.next; // 删除node的后继节点
    }
}

剑指 Offer 18. 删除链表的节点

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode deleteNode(ListNode head, int val) {
        if (head == null) {
            return null;
        }

        ListNode dummy = new ListNode();
        dummy.next = head;
        ListNode p = dummy;

        while (p.next != null) {
            if (p.next.val == val) {
                p.next = p.next.next;
                break;
            }
            p = p.next;
        }

        return dummy.next;
    }
}

203. 移除链表元素

与[上一题](剑指 Offer 18. 删除链表的节点)稍有不同,本题要求删除全部值等于val的值(即链表中的值有重复)。

/**
 * 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 removeElements(ListNode head, int val) {
        if (head == null) {
            return null;
        }

        ListNode dummy = new ListNode();
        dummy.next = head;
        ListNode p = dummy;

        while (p.next != null) {
            if (p.next.val == val) {
                p.next = p.next.next;
            } else { // 与上一题相比,这里加了else,以防最后一个节点被删导致空指针
                p = p.next;
            }
        }

        return dummy.next;
    }
}

19. 删除链表的倒数第 N 个结点【快慢指针】

快指针先走n步,然后快慢指针一起移动。

/**
 * 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) {
        if (head == null) {
            return null;
        }

        ListNode dummy = new ListNode();
        dummy.next = head;
        ListNode slow = dummy, fast = head;
        int k = 0;

        while (k < n) { // 快指针先走n步
            fast = fast.next;
            ++k;
        }
        
        // 快慢指针一起后移
        while (fast != null) {
            slow = slow.next;
            fast = fast.next;
        }

        // 删除(slow的后继节点为要删除的节点)
        slow.next = slow.next.next;

        return dummy.next;
    }
}

2095. 删除链表的中间节点【快慢指针】

/**
 * 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 deleteMiddle(ListNode head) {
        if (head == null || head.next == null) {
            return null;
        }

        // 慢指针一次走一步,快指针一次走两步,pre标记slow的前驱
        ListNode slow = head, fast = head, pre = null;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            pre = slow;
            slow = slow.next;
        }

        pre.next = slow.next;

        return head;
    }
}

1171. 从链表中删去总和值为零的连续节点【前缀和 + HashMap】

用map记录前缀和与对应节点,如果遇到与之前相等的前缀和,则说明两个节点之间的和为0,需要删除,记得要把map中对应的前缀和删掉。

/**
 * 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 removeZeroSumSublists(ListNode head) {
        if (head == null) {
            return null;
        }

        Map<Integer, ListNode> map = new HashMap<>();
        ListNode dummy = new ListNode(0, head);
        ListNode p = head, tail = head;
        int sum = 0;
        map.put(0, dummy);

        while (p != null) {
            sum += p.val;
            if (map.containsKey(sum)) {
                ListNode node = map.get(sum);
                ListNode removeNode = node.next;
                node.next = p.next;
                int dSum = sum;
                while (removeNode != p) { // 删除map中对应的前缀和
                    dSum += removeNode.val;
                    map.remove(dSum);
                    removeNode = removeNode.next;
                }
            } else {
                map.put(sum, p);
            }
            p = p.next;
        }

        return dummy.next;
    }
}

2181. 合并零之间的节点【双指针】

用一个指针tail标记连续非零元素的第一个节点,用指针p向后遍历,将非零元素的val加到tail上,当p遇到零元素:

  • 将tail指向p的后继节点,即新的连续非零元素的第一个节点(也有可能是空,即表尾)。
  • 如果tail是表尾(tail == null),结束。
/**
 * 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 mergeNodes(ListNode head) {
        if (head == null) {
            return null;
        }
        ListNode p = head.next.next, tail = head.next;
        while (p != null) {
            if (p.val != 0) {
                tail.val += p.val;
                p = p.next;
            } else {
                tail.next = p.next;
                tail = tail.next;
                if (tail == null) {
                    break;
                }
                p = tail.next;
            }
        }

        return head.next;
    }
}

83. 删除排序链表中的重复元素

/**
 * 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 deleteDuplicates(ListNode head) {
        ListNode p = head;
        
        while (p != null && p.next != null) {
            if (p.val == p.next.val) { // 跳过p.next这个重复节点
                p.next = p.next.next;
            } else {
                p = p.next;
            }
        }
        
        return head;
    }
}

82. 删除排序链表中的重复元素 II【双指针】

/**
 * 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 deleteDuplicates(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }

        ListNode dummy = new ListNode();
        dummy.next = head;
        ListNode pre = dummy, p = head;

        while (p != null) {
            while (p.next != null && p.val == p.next.val) { // 略过重复值
                p = p.next;
            }

            if (pre.next == p) { // 上面的while没执行,说明这段没有重复值
                pre = pre.next;
            } else { // 有重复值,此时p指向最后一个重复的值
                pre.next = p.next; // pre不能后移,因为不确定新出现的值是否重复
            }
            p = p.next;
        }

        return dummy.next;
    }
}

面试题 02.01. 移除重复节点【Set】

用HashSet标记该元素是否出现过

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode removeDuplicateNodes(ListNode head) {
        if (head == null) {
            return null;
        }

        Set<Integer> set = new HashSet<>();
        set.add(head.val);
        ListNode p = head.next, tail = head;

        while (p != null) {
            if (!set.contains(p.val)) {
                tail.next = p;
                tail = tail.next;
                set.add(p.val);
            }
            p = p.next;
        }
        tail.next = null;

        return head;
    }
}

也可用双重循环,在此就不写代码了。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-11 22:26:29  更:2022-03-11 22:30:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 14:54:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码