leetcode刷题详解四

news2024/11/29 22:32:34
25. K 个一组翻转链表

这道题本质上还是用的反转前n个链表的思想。

具体细节如下:

  1. 先调用一次函数,使用一个newHead接受返回值,这个是为了方便最后函数的返回。

  2. 调用reverseN这个函数的时候,要标记反转这段链表的前置节点和后置节点。后面会用到。

    反转后的这部分区间的链表,node接受前置节点,tail接受后置接点。

  3. 记住,前一个区间的tail节点就是区间中的最后一个节点,这个节点要放到tail_temp中,然后调用reverseN后,会得到新的tail节点,让tail_temp->next指向tail节点,这样两个区间就会接上。

	ListNode* dummy = nullptr;
    ListNode* tail = nullptr;
    
    ListNode* reverseKGroup(ListNode* head, int k) {
        int length = 0;
        ListNode* temp = head;
        
        if(k == 1){
            return head;
        }
        /*计算链表长度*/
        while(temp){
            temp = temp->next;
            length++;
        }
        //减一是因为第一次的时候,要确定head指针
        int loop = length / k - 1;
        ListNode* newHead = reverseN(k, head);
        head = dummy;
        for(int i = 0;i < loop;i++){
            head = dummy;
            ListNode* tail_temp = tail;
            ListNode* node = reverseN(k, head);
            tail_temp->next = node;
        }
        return newHead;
    }

    ListNode* reverseN(int n, ListNode* head){
        if(n == 1){
            dummy = head->next;
            return head;
        }
        ListNode* last = reverseN(n-1, head->next);
        head->next->next = head;
        head->next = dummy;
        tail = head;
        return last;
    }
剑指 Offer 06. 从尾到头打印链表
  • 递归的做法

    其实做了这么多次回头再来看这道题发现一个问题,即链表的本质是改变连接方向就行,而在改变连接方向的时候一定要断开之前的链子,即node->next=null

    vector<int> reversePrint(ListNode* head) {
        vector<int> res;
        ListNode* newHead =  reverse(head);
        while(newHead){
            res.push_back(newHead->val);
            newHead = newHead->next;
        }
        return res;
    }
    
    ListNode* reverse(ListNode* head){
        if(!head || !head->next){
            return head;
        }
        ListNode* tmp = reverse(head->next);
        head->next->next = head;
        head->next = nullptr;
        return tmp;
    }
    
  • 双指针递归的做法

    image-20220227163934553

    这也不失为一种思路

  • 用一个辅助栈就行

  • c++的reverse函数,放到数组里面直接反转

剑指 Offer 24. 反转链表
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
       if(!head || !head->next){
           return head;
       } 
       ListNode* tmp = reverseList(head->next);
       head->next->next = head;
       head->next = nullptr;
       return tmp;
    }
};
剑指 Offer 35. 复杂链表的复制
  • 暴力复制法

    先复制俩表的next节点,然后依次寻找每个节点的random指针,时间复杂度 O ( n 2 ) O(n^2) O(n2)

  • 辅助空间

    整个hash表,记录一下random指针的位置,然后复制的时候填进去就行,空间复杂度 O ( n ) O(n) O(n)

  • 终极牛逼法

    时间复杂度 O ( n ) O(n) O(n)

    image-20220228170737345 image-20220228170847124 image

    第三步就是拆分

    **关键点,不能改原链表,你加完重复链表之后需要复原,!!!**不然会报Next pointer of node with label 7 from the original list was modified.这种错误,表示修改了原链表

    class Solution {
    public:
        Node* copyRandomList(Node* head) {
            if(!head){
                return head;
            }
            Node* new_head = nullptr; 
            new_head = head;
            //重复每个链表节点
            while(new_head){
                Node* tmp = new Node(new_head->val);
                tmp->next = new_head->next;
                new_head->next = tmp;
                new_head = new_head->next->next;
            }
            new_head = head;
            //重定义random指针
            while(new_head){
                if(new_head->random != nullptr){
                    new_head->next->random = new_head->random->next;
                }
                new_head = new_head->next->next;
            }
    
            //把处于偶数的链表拿出来
            Node* copy_head = head->next;
            Node* copy_head_return = head->next;
            new_head = head;
            while(copy_head->next){
                new_head->next = new_head->next->next;
                new_head = new_head->next;
                copy_head->next = new_head->next;
                copy_head = copy_head->next;
            }
            new_head->next = nullptr;
            return copy_head_return;
        }
    };
    

++++

树相关

树题目的总结

个人对递归的一些感悟。

递归的原理非常简单,就是函数出栈入栈。

但很多时候我们都会被递归绕晕,原因就是我们想的太复杂了。做题的时候,一定要先明确函数的定义是什么,然后根据定义来写递归语句。记住,千万不要跳入递归的细节,有时候不考虑细节反而容易实现,考虑细节的话可能会绕进去!

写树相关的算法,简单说就是,先搞清楚当前 root 节点「该做什么」以及「什么时候做」,然后根据函数定义递归调用子节点

把递归的问题放眼到三个节点中,即根节点,右节点左节点。

重中之重!!!!!!!

递归函数什么时候有返回值什么时候没有返回值,比如有 root->left = invertTree(root->left);这种和return searchBST(root->left,val);这两种代码到底有何区别的?

答:有以下三点:

  1. 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。(这种情况就是本文下半部分介绍的113.路径总和ii)
  2. 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。 (这种情况我们在236. 二叉树的最近公共祖先 (opens new window)中介绍)
  3. 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(本题的情况)

普通二叉树相关

226. 翻转二叉树

只要把二叉树上的每一个节点的左右子节点进行交换,最后的结果就是完全翻转之后的二叉树

只能用后序和前序,不能用中序。因为需要交换左右子节点,必须先知道左右子节点。如果用中序的话只知道左节点和根节点,不知道右节点,无法反转。

注意节点交换细节,和普通变量一样

TreeNode* invertTree(TreeNode* root) {
        if(!root){
            return NULL;
        }
        TreeNode* temp = root->left;
        root->left = root->right;
        root->right = temp;

        root->left = invertTree(root->left);
        root->right = invertTree(root->right);
        return root;
    }
112. 路径总和

二叉树路径问题解析

bool hasPathSum(TreeNode* root, int sum) {
    if(!root){
        return false;
    }
    sum -= root->val;
    if(!root->left && !root->right){
        return sum == 0;
    }
    return hasPathSum(root->left, sum) || hasPathSum(root->right, sum);

}
113. 路径总和 II
vector<vector<int>> res;
    vector<int> tmp;
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        recurse(root, targetSum);
        return res;
    }

    void recurse(TreeNode* root, int targetSum){
        if(!root){
            return;
        }
        tmp.push_back(root->val);
        targetSum -= root->val;
        if(!root->left && !root->right && targetSum == 0){
            res.emplace_back(tmp);
        }
        recurse(root->left, targetSum);
        recurse(root->right, targetSum);
        tmp.pop_back();
    }
116. 填充每个节点的下一个右侧节点指针

还是老样子,关注局部的三个节点,根左右,然后写出代码。

img

关键点不是2->3这种一个根节点下的节点,而是5->6这种不在同一个根节点下的。因此要借助5和6的上层节点2,3来解决问题。通过2到3,再到6,就可以链接5和6

Node* connect(Node* root) {
        if(!root){
            return NULL;
        }
        if(root->left){
            root->left->next = root->right;
            if(root->next && root->right){
                root->right->next = root->next->left;
            }
        }
        connect(root->left);
        connect(root->right);
        return root;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1253735.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于C#实现三元组

我们知道矩阵是一个非常强大的数据结构&#xff0c;在动态规划以及各种图论算法上都有广泛的应用&#xff0c;当然矩阵有着不足的地方就是空间和时间复杂度都维持在 N2 上&#xff0c;比如 1w 个数字建立一个矩阵&#xff0c;在内存中会占用 1w*1w1 亿的类型空间&#xff0c;这…

Hadoop实践指南:揭秘HDFS元数据并解析案例

1.什么是元数据 元数据&#xff08;Metadata&#xff09;&#xff0c;描述数据的数据&#xff08;data about data&#xff09;。 1.1 HDFS元数据 元数据&#xff1a;关于文件或目录的描述信息&#xff0c;如文件所在路径、文件名称、文件类型等等&#xff0c;这些信息称为文…

二进制数据转换成十六进制表示 binascii.hexlify()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 二进制数据转换成十六进制表示 binascii.hexlify() 选择题 binascii.hexlify()参数的数据类型可以是&#xff1f; import binascii number 11 byte_data number.to_bytes() hex_data bin…

NX二次开发UF_CURVE_ask_conic_data 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_ask_conic_data Defined in: uf_curve.h int UF_CURVE_ask_conic_data(tag_t conic, UF_CURVE_conic_t * conic_data ) overview 概述 Reads the data from the conic ar…

SSF-CNN:空间光谱融合的卷积光谱图像超分网络

SSF-CNN: SPATIAL AND SPECTRAL FUSION WITH CNN FOR HYPERSPECTRAL IMAGE SUPER-RESOLUTION 文章目录 SSF-CNN: SPATIAL AND SPECTRAL FUSION WITH CNN FOR HYPERSPECTRAL IMAGE SUPER-RESOLUTION简介解决问题网络框架代码实现训练部分运行结果 简介 ​ 本文提出了一种利用空…

基于STC12C5A60S2系列1T 8051单片读写掉电保存数据IIC总线器件24C02多字节并显示在液晶显示器LCD1602上应用

基于STC12C5A60S2系列1T 8051单片多字节读写掉电保存数据IIC总线器件24C02多字节并显示在液晶显示器LCD1602上应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍IIC通…

pytorch分布式训练

1 基本概念 rank&#xff1a;进程号&#xff0c;在多进程上下文中&#xff0c;我们通常假定rank 0是第一个进程或者主进程&#xff0c;其它进程分别具有1&#xff0c;2&#xff0c;3不同rank号&#xff0c;这样总共具有4个进程 node&#xff1a;物理节点&#xff0c;可以是一个…

Java游戏之王者荣耀

首先创建类&#xff1a; 游戏运行结果如下&#xff1a; GameFrame类 所需图片&#xff1a; GameObject类 Turret类 所需图片&#xff1a; TurretBlue类 TurretRed类 Champion类 所需图片&#xff1a; 单个&#xff1a; move包: ChampionDaji类 所需图片&#xff1a; Minio…

css加载会造成阻塞吗??

前言 前几天面试问到了这个问题&#xff0c;当时这个答得不敢确定哈哈&#xff0c;虽然一面还是过了 现在再分析下这个&#xff0c;总结下&#xff0c;等下次遇到就能自信得回答&#xff0c;666 准备工作 为了完成本次测试&#xff0c;先来科普一下&#xff0c;如何利用chr…

输出后,我悟了!

大家好&#xff0c;我是木川 今天和前同事吃饭聊天&#xff0c;谈到了输出&#xff0c;今天简单谈下关于输出的重要性 一、为什么要输出 1、不输出容易忘&#xff0c;如果不输出很容易就忘记了&#xff0c;如果再遇见一次&#xff0c;还是需要重新学习&#xff0c;实际上是浪费…

【如何学习Python自动化测试】—— Python 的 unittest 框架

10 、Python 的 unittest 框架 10.1 Unittest 框架介绍 Unittest是Python语言中的一种测试框架&#xff0c;是Python标准库中的一个模块。它可以帮助开发者编写自动化测试&#xff0c;可以进行单元测试、集成测试、功能测试等各种类型的测试。 Unittest的特点是简单易学&#…

用 Addon 增强 Node.js 和 Electron 应用的原生能力

前言 Node.js Addon 是 Node.js 中为 JavaScript 环境提供 C/C 交互能力的机制。其形态十分类似 Java 的 JNI&#xff0c;都是通过提供一套 C/C SDK&#xff0c;用于在 C/C 中创建函数方法、进行数据转换&#xff0c;以便 JavaScript / Java 等语言进行调用。这样编写的代码通常…

突破技术障碍:软件工程师如何应对项目中的难题?

在软件开发项目中&#xff0c;工程师常常会遇到各种技术难题。这些难题可能涉及到复杂的算法、不兼容的系统、难以预见的软件行为&#xff0c;或者其他许多方面。 以下是一些策略和方法&#xff0c;可以帮助软件工程师有效地应对这些挑战&#xff1a; 1、理解问题&#xff1a;…

MySQL数据库——存储函数(介绍、案例)

目录 介绍 案例 介绍 存储函数是有返回值的存储过程&#xff0c;存储函数的参数只能是IN类型的。具体语法如下&#xff1a; CREATE FUNCTION 存储函数名称 ([ 参数列表 ]) RETURNS type [characteristic ...] BEGIN-- SQL语句RETURN ...;END ; characteristic说明&#xf…

Matplotlib子图的创建_Python数据分析与可视化

Matplotlib子图的创建 plt.axes创建子图fig.add_axes()创建子图 plt.axes创建子图 前面已经介绍过plt.axes函数&#xff0c;这个函数默认配置是创建一个标准的坐标轴&#xff0c;填满整张图。 它还有一个可选的参数&#xff0c;由图形坐标系统的四个值构成。这四个值表示为坐…

05 _ 系统设计目标(三):如何让系统易于扩展?

从架构设计上来说&#xff0c;高可扩展性是一个设计的指标&#xff0c;它表示可以通过增加机器的方式来线性提高系统的处理能力&#xff0c;从而承担更高的流量和并发。 你可能会问&#xff1a;“在架构设计之初&#xff0c;为什么不预先考虑好使用多少台机器&#xff0c;支持…

C语言之指针知识点总结

C语言之指针知识点总结 文章目录 C语言之指针知识点总结1. 初识指针1.1 取地址操作符 &1.2 指针变量1.3 解引用操作符 *1.4 指针变量1.4.1 大小1.4.2 指针类型的意义 1.5 void*指针1.6 const关键字1.61 const修饰变量1.6.2 const修饰指针变量 1.7 指针的运算1.7.1 指针-整数…

堆和栈的区别 重点来说一下堆和栈;堆与栈之间的联系

文章目录 堆和栈的区别重点来说一下堆和栈&#xff1a;那么堆和栈是怎么联系起来的呢? 堆与栈的区别 很明显&#xff1a; 今天来聊一聊java中的堆和栈&#xff0c;工作当中这两个也是经常遇到的&#xff0c;知识我们没有去注意理论上的这些内容&#xff0c;今天就来分享一下。…

MIPI 打怪升级之DSI篇

MIPI 打怪升级之DSI篇 目录 1 Overview2 DSI Mode 2.1 Video 模式2.2 Command 模式3 DSI Physical Layer 3.1 数据流控3.2 双向性3.3 Video Mode Interfaces3.4 Command Mode Interfaces3.5 Clock4 多通道管理 4.1 通道数匹配4.2 线上数据分布5 DSI 协议 5.1 包格式 5.1.1 短包…

Scrapy爬虫异步框架(一篇文章齐全)

1、Scrapy框架初识 2、Scrapy框架持久化存储&#xff08;点击前往查阅&#xff09; 3、Scrapy框架内置管道&#xff08;点击前往查阅&#xff09; 4、Scrapy框架中间件&#xff08;点击前往查阅&#xff09; Scrapy 是一个开源的、基于Python的爬虫框架&#xff0c;它提供了…