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——203. 移除链表元素/707. 设计链表/206. 反转链表/24. 两两交换链表中的节点 -> 正文阅读

[数据结构与算法]Leetcode——203. 移除链表元素/707. 设计链表/206. 反转链表/24. 两两交换链表中的节点

概述

203. 移除链表元素

707. 设计链表

206. 反转链表

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

  • 上述四个题目,算法的技巧都在建立虚拟头结点,来统一操作

分析

  • 对于链表来说,头结点相当于其他结点处在一个特殊位置:其他结点都有前、后结点(尾结点的后结点时NULL),而头结点确没有前结点

  • 所以,经常会需要额外考虑头结点的处理

  • 为了同一操作,可以为原始链表添加一个虚拟头结点,指向原始头结点,使得对于原始链表来说,所有结点都是一样的结构,用于前、后结点

思路

如何添加虚拟头结点?

  • ListNode *virtual_head = new ListNode();
    virtual_head -> next = head;
    

代码

203

移除链表中满足Node.val == val 的节点,通过使用虚拟头结点来统一对原始链表头结点的删除操作

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        // 构造虚拟头结点,链接原始链表
        ListNode *virtual_head = new ListNode();
        virtual_head->next = head;      
        // 省略了delete删除物理结点的操作
        ListNode *pre_ptr = virtual_head;
        ListNode *work_prt = head;
        while(work_prt) {
            if (work_prt -> val == val) {   
                pre_ptr -> next = work_prt->next;       // 逻辑上,在链表中删除该结点
                work_prt = pre_ptr->next;       // 下一个工作结点
            } else {
                pre_ptr = pre_ptr -> next;
                work_prt = work_prt -> next;
            }
        }
        return virtual_head -> next;
    }
};

707

利用虚拟头结点来统一操作

class MyLinkedList {
public:

    struct LinkNode{		// 内部结点实现
        int val;
        LinkNode *next;
    };

    MyLinkedList() {
        size = 0;
        virtual_node = new LinkNode();      // 创建虚拟头结点
    }
    
    int get(int index) {
        if (index < 0 || index >= size)  return -1;
        LinkNode *work_ptr = virtual_node;      // 非特殊必要,wokr_ptr从虚拟头结点开始较好
        int count = 0;
        while(work_ptr -> next) {			// 循环判断
            work_ptr = work_ptr -> next;
            if (count == index) return work_ptr -> val;
            ++count;
        }
        return -1;
    }
    
    void addAtHead(int val) {
        LinkNode *new_node = new LinkNode();
        new_node -> val = val;
        new_node -> next = virtual_node -> next;
        virtual_node -> next = new_node;
        ++size;
    }
    
    void addAtTail(int val) {
        LinkNode *new_node = new LinkNode();
        new_node -> val = val;

        LinkNode *work_ptr = virtual_node;
        while(work_ptr -> next) work_ptr = work_ptr -> next;
        work_ptr -> next = new_node;
        ++size;
    
    }
    
    void addAtIndex(int index, int val) {
        if (index <= 0) {
             addAtHead(val);
             return;
        }
        if (index == size){
              addAtTail(val);
              return;
        }
        if (index > size)  return;

        LinkNode *new_node = new LinkNode();
        new_node -> val = val;

        LinkNode *pre_ptr = virtual_node;
        LinkNode *work_ptr = virtual_node -> next;      // 特殊情况,work_ptr从实际的头结点,即virtual_head -> next开始
        int count = 0;
        while(work_ptr){    		// while条件
            if(count == index) {
                pre_ptr -> next = new_node;
                new_node -> next = work_ptr;
                break;
            }
            work_ptr = work_ptr -> next;
            pre_ptr = pre_ptr -> next;
            ++count;
        }
        ++size;
    }
    
    void deleteAtIndex(int index) {
        if (index < 0 || index >= size) return;

        LinkNode *pre_ptr = virtual_node;
        LinkNode *work_ptr = virtual_node -> next;      // 特殊情况
        int count = 0;
        while(work_ptr){
            if(count == index) {
                pre_ptr -> next = work_ptr -> next;
                delete work_ptr;
                break;
            }
            pre_ptr = pre_ptr -> next;
            work_ptr = work_ptr -> next;
            ++count;
        }
        --size;
        
    }
private:
    int size;                   // 记录链表长度;
    LinkNode *virtual_node;     // 虚拟头结点
};

206

创建虚拟头结点,利用头插法构建原始链表的逆序链表

class Solution {
public:
    // 头插法
    ListNode* reverseList(ListNode* head) {
        ListNode * virtual_head = new ListNode();
        
        ListNode *work_ptr = head;
        while(work_ptr) {
            ListNode *temp = work_ptr -> next;
            work_ptr -> next = virtual_head -> next;
            virtual_head -> next = work_ptr;
            work_ptr = temp;
        }
        return virtual_head->next;
    }
};

24

利用虚拟头结点,统一对原始链表头结点的操作

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode *virtual_head = new ListNode();
        virtual_head -> next = head;
        ListNode *pre_ptr = virtual_head;
        ListNode *work_ptr = head;
        while(work_ptr && work_ptr -> next) {
            // 更新过程要想清楚
            ListNode *next_ptr = work_ptr -> next;
            pre_ptr -> next = next_ptr;
            work_ptr -> next = next_ptr -> next;
            next_ptr -> next = work_ptr;
            pre_ptr = work_ptr;
            work_ptr = pre_ptr -> next;
        }
        return virtual_head -> next;
    }
};

考虑:

当我们使用了虚拟头结点时,工作指针wokr_ptr从虚拟头结点开始较好,此时利用while遍历循环的条件是while(work_ptr -> next)

因为只有这样,才能确保第一次的work_ptr一定有效。

如果需要前后两个指针,则work_ptr需要指向work_ptr -> next,此时while遍历循环的条件是while(work_ptr),因为原始链表可能为空

这段分析,可参考题目707的注释理解

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-01 15:57:51  更:2022-05-01 15:58:39 
 
开发: 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 5:48:35-

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