【剑指offer】学习计划day2

这篇具有很好参考价值的文章主要介绍了【剑指offer】学习计划day2。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【剑指offer】学习计划day2

目录

一. 前言 

二.从尾到头打印链表

        a.题目

         b.题解分析

          c.AC代码

  三. 反转链表

         a.题目

         b.题解分析

        c.AC代码 

四. 复杂链表的复制

         a.题目

         b.题解分析

         c.AC代码


一. 前言 

 本系列是针对Leetcode中剑指offer学习计划的记录与思路讲解。详情查看以下链接:

剑指offer-学习计划https://leetcode.cn/study-plan/lcof/?progress=x56gvoct

    本期是本系列的day2,今天的主题是----》链表(简单)

    题目编号:JZ06,JZ24,JZ35

二.从尾到头打印链表

        a.题目

【剑指offer】学习计划day2

         b.题解分析

       这题的方法有很多。其一:我们可以先遍历一遍链表,将节点的值放到一个数组中,最后将数组逆置即可。其二:我们可以使用一个辅助栈,利用栈后入先出的特性,将链表每个节点的值压入栈中,然后再依次出栈到数组即可。其三:利用递归,先走至链表末端,回溯时依次将节点值放入 数组返回即可。

          c.AC代码

//普通遍历
int* reversePrint(struct ListNode* head, int* returnSize)
{
	int* ret=(int*)malloc(sizeof(int) * 10000);
	int count = 0;
	struct ListNode* cur = head;
    //将每个节点的值放入数组
	while (cur)
	{
		ret[count++] = cur->val;
		cur = cur->next;
	}
	int left = 0;
	int right = count-1;
    //逆置数组
	while (left < right)
	{
		int tmp = ret[left];
		ret[left] = ret[right];
		ret[right] = tmp;
		left++;
		right--;
	}
	*returnSize = count;
	return ret;
}
//递归法

int ret[10000] = { 0 };//全局数组,用于存放逆序的链表
int* reversePrint(struct ListNode* head, int* returnSize)
{
	if (head == NULL)//到链表尾,开始返回
	{
		*returnSize = 0;
		return NULL;
	}
	reversePrint(head->next, returnSize);
	ret[*returnSize] = head->val;
	(*returnSize)++;
	return ret;
}

  三. 反转链表

         a.题目

【剑指offer】学习计划day2

         b.题解分析

       本题我们在之前的单链表刷题篇有遇到过,当时我们采用了三种方法:三指针法头插法

递归。我们这里便不再细谈,不了解的小伙伴们可以跳转到往期:【刷题篇】链表(上)http://t.csdn.cn/LcalP

        c.AC代码 

//三指针法
struct ListNode* reverseList(struct ListNode* head)
{
    struct ListNode* n1 = NULL;
    struct ListNode* n2 = head;

    while (n2)
    {
        struct ListNode* n3 = n2->next; //保存下一结点位置
        n2->next = n1;
        n1 = n2;
        n2 = n3;
    }
    //n2为空时,n1即为反转后表头
    return n1;
}
//头插法
struct ListNode* reverseList(struct ListNode* head)
{
    struct ListNode* newhead = NULL; //新链表
    struct ListNode* first = head;
    while (first)
    {
        struct ListNode* next = first->next; //保存下一结点
        //进行头插
        first->next = newhead;
        newhead = first;
        first = next;
    }
    //全部结点头插完毕
    return newhead;

}
//递归法
struct ListNode* reverseList(struct ListNode* head) 
{
    if (head == NULL || head->next == NULL) //当只有一个结点、没有结点、递归到最后一个结点时返回
        return head;
    struct ListNode* cur = reverseList(head->next); //找到链表尾结点
    head->next->next = head; //让下一结点指向当前结点
    head->next = NULL; //当前结点指向空
    return cur; //返回反转后头结点
}

四. 复杂链表的复制

         a.题目

【剑指offer】学习计划day2

         b.题解分析

        本题要求我们对一个复杂链表进行一个深拷贝。假如这只是一个普通的单链表,那我们就可以一边遍历链表一边创建结点,当遍历结束时我们的复制也就完成了。但是这个链表除了有next指针指向下一个结点,还存在着一个随机指针random指向随机的结点。这就意味着当我们复制结点时random指向的结点我们可能还没有创建,如下图所示。所以我们需要变换思路。

【剑指offer】学习计划day2

        法一:原地+结点拆分

        我们先遍历一遍链表,将每个结点进行复制后放入原结点的后面。然后再第二次遍历给复制的结点的random指针赋值,这样可以确保random指向的结点已经存在。最后再将链表中复制的结点进行拆分,形成一个新链表,返回即可。时间复杂度O(N),空间复杂度O(1)

【剑指offer】学习计划day2

        法二:哈希表

        我们也可以利用哈希表的查询功能来解题。先遍历一遍链表进行拷贝,每次拷贝结点时在哈希表中构建原结点和新结点的映射关系。然后根据原结点和新结点的映射关系再次遍历一遍链表给新结点的next指针和random指针进行赋值即可。时间复杂度O(N),空间复杂度O(N)

【剑指offer】学习计划day2 

         c.AC代码 

//法1,原地+结点拆分

class Solution
{
public:
    Node* copyRandomList(Node* head)
    {
        if (head == NULL)
        {
            return NULL;
        }
        //复制结点到当前结点后
        for (Node* cur = head; cur; cur=cur->next->next)
        {
            Node* pnode = new Node(cur->val);
            pnode->next = cur->next;
            cur->next = pnode;
        }
        //对复制的结点的random指针赋值
        for (Node* cur = head; cur; cur=cur->next->next)
        {
            if (cur->random)
            {
                cur->next->random = cur->random->next;
            }
        }

        //每隔一项进行拆分
        Node* retNode = head->next;//指向新链表的头
        for (Node* cur = head; cur; )
        {
            Node* next = cur->next;
            if (next)
            {
                cur->next = next->next;
            }
            cur = next;
        }
        return retNode;

    }
};
//法2,哈希表

class Solution
{
public:
    Node* copyRandomList(Node* head) 
    {
        unordered_map<Node*, Node*> value;//哈希表,建立索引
        value[NULL] = NULL;
        //第一次遍历建立索引映射
        for (Node* cur = head; cur; cur = cur->next)
        {
            value[cur] = new Node(cur->val);
        }
        //第二次遍历对新结点的指针进行赋值链接
        for (Node* cur = head; cur; cur = cur->next)
        {
            value[cur]->next = value[cur->next];
            value[cur]->random= value[cur->random];
        }
        return value[head]; 
    }
};

以上,就是本期的全部内容啦🌸

制作不易,能否点个赞再走呢🙏文章来源地址https://www.toymoban.com/news/detail-446626.html

到了这里,关于【剑指offer】学习计划day2的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【剑指offer|图解|链表】删除链表的节点 + 训练计划 V

    🏠 个人主页:@聆风吟的个人主页 🔥系列专栏:本期文章收录在专栏《剑指offer每日一练》中,大家有兴趣可以浏览和关注,后面将会持续更新更多精彩内容! ⏰寄语:少年有梦不应止于心动,更要付诸行动。 🎉欢迎大家关注🔍点赞👍收藏⭐️评论📝 🌈作者留言:文章

    2024年02月08日
    浏览(38)
  • 剑指offer题解合集——Week3day6

    题目链接:栈的压入、弹出序列 AC代码 思路: 整体思路 题目链接:不分行从上往下打印二叉树 AC代码 思路: 整体思路

    2024年01月19日
    浏览(38)
  • 剑指offer题解合集——Week3day4

    题目链接:二叉树的镜像 AC代码 思路: 整体思路 题目链接:对称的二叉树 AC代码 思路: 整体思路

    2024年02月02日
    浏览(31)
  • 黑马机器学习day2

    转换器和预估器(estimator) 实例化一个转换器类        Transformer 调用fit_transform() 转换器调用有以下几种形式: fit_transform fit transform 在sklearn中,估计器是一个重要的角色,是一类实现了算法的API 1、用于分类的估计器: 1)sklearn.neighbors k近邻算法 2)sklearn.native_bayes 贝叶斯

    2024年02月13日
    浏览(30)
  • Go学习-Day2

    个人博客 驼峰法,首字母大写可以在其他包里使用,首字母小写只能在本包内使用 跨包使用,的import地址从src的子目录开始,src以及src所在的GOPATH自动补全 定义变量 var+变量名+变量类型 自动推断类型 简略写法 对应的,可以声明多个变量 另一种声明方法,开发中常用

    2024年02月12日
    浏览(30)
  • C++学习(day2)

    C语言风格的字符串依然支持,使用字符数组的形式存储字符串,字符串标志:‘\\0’ C++风格的字符串,本质上是string类的对象 使用要求:需要加头文件:#include 单个数据的初始化和赋值 方式 解释 方式1 string s2 = “ni hao”; 方式2 string s3(“shang hai”); 方式3 string s4{“zhangpeng

    2023年04月24日
    浏览(28)
  • 【cs61b】学习笔记day2

    【cs61b】学习笔记day1 思考下面两个代码分别输出什么 从下图可以看出,a和b指向的同一个实例,而x和y是两个独立的 在计算机中,数字72和大写字母H都是以01001000来存储,那么java是如何区分他们的? 答: 以类型区分 在Java, 有8 八种基本类型: byte, short, int, long, float, double, b

    2024年02月13日
    浏览(26)
  • Vue3 学习笔记(Day2)

    「写在前面」 本文为尚硅谷禹神 Vue3 教程的学习笔记。本着自己学习、分享他人的态度,分享学习笔记,希望能对大家有所帮助。推荐先按顺序阅读往期内容: 1. Vue3 学习笔记(Day1) 目录 3 Vue3 核心语法 3.1 选项式API 与 组合式API 3.2 setup 3.3 ref 和 reactive 3.4 computed 3.5 watch 3.

    2024年02月22日
    浏览(38)
  • flutter学习-day2-认识flutter

    本文学习和引用自《Flutter实战·第二版》:作者:杜文 Flutter 是 Google 推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。开发者可以通过 Dart 语言开发 App,一套代码同时运行在 iOS 和 Android平台。 Flutter 提供了丰富的组件、接口,开发者可以很快地为 Flutter 添加

    2024年02月04日
    浏览(31)
  • 【Node.js学习 day2——预备知识】

    1、概念 Buffer是一个类似于数组的对象,用于表示固定长度的字节序列 Buffer本质是一段内存空间,专门用来处理二进制数据 2、特点 Buffer大小规定且无法调整 Buffer性能较好,可以直接对计算机内存进行操作 每个元素的大小为1字节(byte) 3、使用 创建Buffer(3种方式) 4、 B

    2024年01月25日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包