leetcode刷题详解四

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.mfbz.cn/a/188223.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用户与组管理:如何在服务器系统中管理用户和权限

你是否想过&#xff0c;当你登录到一个服务器系统时&#xff0c;你是如何被识别和授权的&#xff1f;你是否知道&#xff0c;你可以通过创建和管理用户和组来简化和优化你的系统管理工作&#xff1f;你是否想了解一些常用的用户和组管理命令和技巧&#xff1f;如果你的答案是肯…

接口测试场景:怎么实现登录之后,需要进行昵称修改?

在接口测试中有一个这样的场景&#xff1a;登录之后&#xff0c;需要进行昵称修改&#xff0c;怎么实现&#xff1f; 首先我们分别看下登录、昵称修改的接口说明&#xff1a; 以上业务中补充一点&#xff0c;昵称修改&#xff0c;还需要添加请求头Authorization传登录获取的to…

03_MySQL基本SQL语句讲解

#课程目标 能够创建、删除数据表能够对表里的数据记录进行增加、删除、修改、查询操作能够创建、删除用户能够给用户授权并回收权限了解delete和truncate语句的区别 #一、数据库基本操作 ##1、查看数据库相关信息 mysql> show databases; 查看所有数据库 mysql>…

js逆向-某敏感网站登录参数分析

声明 本文仅供学习参考&#xff0c;如有侵权可私信本人删除&#xff0c;请勿用于其他途径&#xff0c;违者后果自负&#xff01; 如果觉得文章对你有所帮助&#xff0c;可以给博主点击关注和收藏哦&#xff01; 前言 目标网站&#xff1a;aHR0cHM6Ly9tZGZnaGcuNXhwb2lqaHRm…

字符串转换成十进制整数

编程要求 输入一个以#结束的字符串&#xff0c;本题要求滤去所有的非十六进制字符&#xff08;不分大小写&#xff09;&#xff0c;组成一个新的表示十六进制数字的字符串&#xff0c;然后将其转换为十进制数后输出。如果在第一个十六进制字符之前存在字符“-”&#xff0c;则…

【阿里云】图像识别 智能分类识别 增加网络控制功能点(三)

一、增加网络控制功能 实现需求TCP 心跳机制解决Soket异常断开问题 二、Linux内核提供了通过sysctl命令查看和配置TCP KeepAlive参数的方法。 查看当前系统的TCP KeepAlive参数修改TCP KeepAlive参数 三、C语言实现TCP KeepAlive功能 四、setsockopt用于设置套接字选项的系…

王者荣耀——Java

代码如下&#xff1a; sxt Background package sxt;import java.awt.*; //背景类 public class Background extends GameObject{public Background(GameFrame gameFrame) {super(gameFrame);}Image bg Toolkit.getDefaultToolkit().getImage("C:\\Users\\24465\\Desk…

linux账户管理实例二

要求&#xff1a;我的 用户pro1&#xff0c;pro2&#xff0c;pro3是同一个项目开发人员&#xff0c;想让这三个人用户在同一个目录下工作&#xff0c;但这三个人拥有自己的主文件夹和基本的私有用户组&#xff0c;工作目录为/srv/projecta&#xff0c;如何实现&#xff1f; 分…

吴恩达《机器学习》10-1-10-3:决定下一步做什么、评估一个假设、模型选择和交叉验证集

一、决定下一步做什么 在机器学习的学习过程中&#xff0c;我们已经接触了许多不同的学习算法&#xff0c;逐渐深入了解了先进的机器学习技术。然而&#xff0c;即使在了解了这些算法的情况下&#xff0c;仍然存在一些差距&#xff0c;有些人能够高效而有力地运用这些算法&…

浅析智能电能表远程费控的推广及应用

安科瑞 华楠 摘 要: 电力资源是我国社会发展中一种必不可少的资源,随着我国经济的不断发展和人们生活水平的不断提升,对电力行业的要求也不断提升。因此,电力企业应该不断提升自身的服务水平和服务质量,强智能电能表远程费控的推广与应用,提升电力计量和收费工作的效率,提高电…

Java基础(第九期):Java中的集合 ArrayList 集合的增删改查 Java实现学生信息管理系统

⚠️Java基础专栏 文章目录 ⚠ Java基础最后一期&#xff08;第九期&#xff09;到此结束 Java中的集合一、什么是集合二、ArrayList2.1 ArrayList介绍2.2ArrayList使用2.3 ArrayList添加add&#xff08;&#xff09;方法add&#xff08;index&#xff0c;E element&#xff0…

4.28每日一题(二重积分比较大小:被积函数的大小、正负性、积分区间奇偶性)

一般比较大小的题目我们不需要把结果全部计算出来 &#xff0c;而是通过奇偶性或者被积函数的大小或大于0、等于0、小于0等方法判断比较

PostgreSQL 分区表插入数据及报错:子表明明存在却报不存在以及column “xxx“ does not exist 解决方法

PostgreSQL 分区表插入数据及报错&#xff1a;子表明明存在却报不存在以及column “xxx“ does not exist 解决方法 问题1. 分区表需要先创建子表在插入&#xff0c;创建子表立马插入后可能会报错子表不存在&#xff1b;解决&#xff1a; 创建子表及索引后&#xff0c;sleep10毫…

Linux的基本指令 ( 一 )

目录 前言 Linux基本指令 快速认识五个指令 ls指令 补充内容 pwd指令 补充内容 cd指令 补充内容 重新认识指令 指令的本质 which指令 alias指令 最后 一个文件的三种时间 tree指令及安装 tree指令 前言 关于Linux操作系统的桌面&#xff0c;在学校教学中我们…

【蓝桥杯】刷题

刷题网站 记录总结刷题过程中遇到的一些问题 1、最大公约数与最小公倍数 a,bmap(int,input().split())sa*bwhile a%b:a,bb,a%bprint(b,s//b)2.迭代法求平方根(题号1021) #include<stdio.h> #include<math.h> int main() {double x11.0,x2;int a;scanf("%d&…

FFmpeg零基础学习(一)——初步介绍与环境搭建

目录 前言正文一、开发环境二、搭建环境三、测试代码四、调用库的介绍End、遇到的问题2、Qt 在线安装容易报错&#xff0c;断开问题1、在线安装QMaintainTool很慢2、Qt5.15 无法调试FFmpeg 参考 前言 FFmpeg是一个开源的跨平台多媒体处理框架&#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 短包…

上新!2023年汉字小达人市级比赛在线模拟题增加2个刷题试卷

各位小学三年级到五年级的上海学霸孩子们&#xff0c;刚刚结束了上海小学生古诗文大会的复赛&#xff0c;就紧锣密鼓地全身心投入到上海小学生汉字小达人的市级比赛的备赛中了。 为了助各位孩子一臂之力&#xff0c;我把在线模拟题进行了更新&#xff0c;新增了两个可以刷题的试…

SparkSQL之Optimized LogicalPlan生成过程

经过Analyzer的处理&#xff0c;Unresolved LogicalPlan已经解析成为Analyzed LogicalPlan。Analyzed LogicalPlan中自底向上节点分别对应Relation、Subquery、Filter和Project算子。   Analyzed LogicalPlan基本上是根据Unresolved LogicalPlan一对一转换过来的&#xff0c;…

细胞级浮游藻类智能检测系统

产品信息 新一代浮游藻类智能检测系统问世&#xff01;英视江河首次将藻类检测精度提升到细胞级&#xff01;英视江河致力于新一代浮游生物的识别、计数。特征是群体藻类和群体种个体均精准检测&#xff01;目前设备已在山东、宁夏、内蒙多地实际应用。 郑州英视江河生态环境科…