leetcode刷题详解三

2. 两数相加

思路:直接加,注意进位条件不要用if,核心代码在于sum = l1->val + l2->val + carry;

ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* dummy = new ListNode();
        ListNode* dummy_head = dummy;
        int carry = 0;
        int sum = 0;
        int single = 0;
        while(l1 && l2){
            sum = l1->val + l2->val + carry;
            carry = sum / 10;
            single = sum % 10;
            ListNode* node = new ListNode(single);
            dummy -> next = node;
            dummy = dummy->next;
            l1 = l1->next;
            l2 = l2->next;
        }
        while(l1){
            sum = l1->val + carry;
            carry = sum / 10;
            single = sum % 10;
            ListNode* node = new ListNode(single);
            dummy -> next = node;
            dummy = dummy->next;
            l1 = l1->next;
        }
        while(l2){
            sum = l2->val + carry;
            carry = sum / 10;
            single = sum % 10;
            ListNode* node = new ListNode(single);
            dummy -> next = node;
            dummy = dummy->next;
            l2 = l2->next;
        }
        if(carry){
            ListNode* node = new ListNode(carry);
            dummy -> next = node;
            dummy = dummy->next;
        }
        return dummy_head->next;
    }
445. 两数相加 II

思路:用栈,这样如果两个链表长度不相等的时候不用那么麻烦。

难点在于代码的细节控制。

  1. 当代码中出现空栈时候,则对应的数置为0,不要再写if判断了。
  2. 用第三个栈重建一个链表,这样耗费空间。可以参考第一种写法,总之这道题在于细节控制,思想上不难。
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        stack<int> s1;
        stack<int> s2;
        int carry = 0;
        int sum = 0;
        int single = 0;
        ListNode* dummy = new ListNode();
        ListNode* dummy_head = dummy;

        while(l1){
            s1.push(l1->val);
            l1=l1->next;
        }
        while(l2){
            s2.push(l2->val);
            l2 = l2->next;
        }
        
        while(!s1.empty() && !s2.empty()){
            sum  = s1.top() + s2.top() + carry;
            single = sum % 10;
            carry = sum / 10;
            ListNode * tmp = new ListNode(single);
            dummy -> next = tmp;
            dummy = dummy->next;
            s1.pop();
            s2.pop();
        }
        while(!s1.empty()){
            sum  = s1.top() + carry;
            single = sum % 10;
            carry = sum / 10;
            ListNode * tmp = new ListNode(single);
            dummy -> next = tmp;
            dummy = dummy->next;
            s1.pop();
        }
        while(!s2.empty()){
            sum  = s2.top() + carry;
            single = sum % 10;
            carry = sum / 10;
            ListNode * tmp = new ListNode(single);
            dummy -> next = tmp;
            dummy = dummy->next;
            s2.pop();
        }
        if(carry){
            ListNode * tmp = new ListNode(carry);
            dummy -> next = tmp;
            dummy = dummy->next;
        }

        ListNode* reverse_head = reverse(dummy_head->next);
        return reverse_head;
    }

    ListNode* reverse(ListNode* node){
        if(!node || !node->next){
            return node;
        }
        ListNode* tmp = reverse(node->next);
        node->next->next = node;
        node->next = nullptr;
        return tmp;
    }
725. 分隔链表

思路:这道题就是先求出链表长度,然后分段。

主要难点在于断链,vector每一个索引都是一个链表,在锻炼表操作这里我足足困了好长时间

其实重点就两句话:dummy = root;
root = root->next;(这个代码是设置前置节点的最好办法)

因为我们要找到前置节点,其实很简单dummy = root 中dummy就可以变成前置节点了!!!

vector<ListNode*> splitListToParts(ListNode* root, int k) {        
    //计算长度        
    int length = 0;        
    ListNode* temp = root;        
    while(temp){            
        length++;            
        temp = temp->next;        
    }        
    //每个断链的长度        
    int arry_len = (length / k) > 0 ? (length / k) : 1;        
    int arry[k];        
    for(int i = 0;i < k; i++){            
        arry[i] = arry_len;        
    }        
    //因为长度差不超过一,因此根据length和k*arry_len的差依次给前面的每个值+1        
    int gap = 0;        
    if((k * arry_len) < length){            
        gap = length - (k * arry_len);            
        for(int i = 0;i < gap;i++){                
            arry[i]++;            
        }        
    }                
    //断链表操作        
    vector<ListNode*> splict;        
    ListNode* dummy ;        
    for(int i = 0; i < k; i++){            
        splict.push_back(root);            
        for(int j = 0;j < arry[i];j++){                
            if(root){                    
                dummy = root;/*前置结点的精髓所在*/                    
                root = root->next;                
            }                          
        }
        if(dummy){                    
             dummy->next = NULL;                
        }  
    }        
    return splict;    
}
328. 奇偶链表

双指针然后拼接

ListNode* oddEvenList(ListNode* head) {
    if(!head || !head->next || !head->next->next){
        return head;
    }
    ListNode* odd = head;
    ListNode* even = head->next;
    ListNode* dummy = even;
    while(odd->next && even->next){
        odd->next = even->next;
        odd = odd->next;
        even->next = odd->next;
        even = even->next;
    }
    odd->next = dummy;
    return head;
}
⭕️92. 反转链表 II

反转链表精髓:

image

关于反转链表相关的递归思想,看这个

这个反转链表,思想和反转前n个链表一模一样。

只不过,第一个left不是从1开始反转,那又如何?我们可以让他变成从1开始,想一想。

反转前n个链表

img
ListNode* temp = nullptr;
    ListNode* reverseN(int n,ListNode* node){
        if(n == 1){
            temp = node->next;
            return node;
        }

        ListNode* last = reverseN(n-1, node->next);
        node->next->next = node;
        node->next = temp;
        return last;
    }

这道题解,递归解法----反转链表递归解法还是比较简单的

ListNode* reverseBetween(ListNode* head, int left, int right) {
        ListNode* dummy = head;
        ListNode* n1 = nullptr;
        int length = right - left +1;
        while(left > 1){
            n1 = dummy;/*记录前一个节点*/
            dummy = dummy->next;
            left--;
        }
        ListNode* n2 = reverseN(length, dummy);
    	//n1为空说明left就是1,从第一个位置反转的!!!
        if(n1){
            n1->next = n2;
        }else{
            return n2;
        }
        return head;
    }

    ListNode* temp = nullptr;
    ListNode* reverseN(int n,ListNode* node){
        if(n == 1){
            temp = node->next;
            return node;
        }

        ListNode* last = reverseN(n-1, node->next);
        node->next->next = node;
        node->next = temp;
        return last;
    }

/*******************第二种解法***********************/
/*有两个dummy节点,begin前和end后,因此要判断四次*/
ListNode* reverseBetween(ListNode* head, int left, int right) {
    if(!head || !head->next){
        return head;
    }
    ListNode* begin = head;
    ListNode* end = head;
    ListNode* dummy = nullptr;
    while(left > 1){
        dummy = begin;
        begin = begin->next;
        left--;
    }
    while(right > 1){
        end = end->next;
        right--;
    }
    ListNode* dummy2 = end->next;
    ListNode* node = reverse(begin, end);
    if(!dummy && !dummy2){
        cout<<"1"<<endl;
        return end;
    }
    else if(!dummy && dummy2){
        cout<<"2"<<endl;
        begin->next = dummy2;
        return end;
    }
    else if(dummy && !dummy2){
        cout<<"3"<<endl;
        dummy->next = end;
        return head;
    }
    cout<<"4"<<endl;
    dummy->next = node;
    begin->next = dummy2;
    return head;
}

ListNode* reverse(ListNode* begin, ListNode* end){
    if(begin == end){
        return begin;
    }
    ListNode* tmp = reverse(begin->next, end);
    begin->next->next = begin;
    begin->next = nullptr;
    return tmp;
}
83. 删除排序链表中的重复元素
b805fe719e7b0bce53d3e78d4575ed3

思路如图所示,很好理解。

ListNode* deleteDuplicates(ListNode* head) {
        if(!head || !head->next){
            return head;
        }
        int value = head->val;
        ListNode* temp = head->next;
        ListNode* carry = head;
        while(temp){
            if(temp->val == value){
                ListNode* dummy = temp;
                temp = temp->next;
                carry->next = temp;
                delete dummy;
                dummy = nullptr;
            }else{
                carry = carry->next;
                value = carry->val;
                temp = temp->next;
            }
        }
        return head;
    }

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

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

相关文章

Ubuntu 22.04.3编译AOSP13刷机

文章目录 设备信息下载AOSP并切换分支获取设备驱动编译系统编译遇到的问题Cannot allocate memoryUbuntu设置USB调试刷机参考链接 设备信息 手机&#xff1a;Pixel 4XL 下载AOSP并切换分支 在清华大学开源软件镜像站下载初始化包aosp-latest.tar。 解压缩&#xff0c;切换到…

【汉诺塔 —— (经典分治递归)】

汉诺塔 —— &#xff08;经典分治递归&#xff09; 一.汉诺塔介绍二.分治算法解决汉诺塔问题三.汉诺塔问题的代码实现四.主函数测试展示 一.汉诺塔介绍 汉诺塔问题源自印度一个古老的传说&#xff0c;印度教的“创造之神”梵天创造世界时做了 3 根金刚石柱&#xff0c;其中的一…

机器视觉尺寸测量仪 助力打造智能工厂!

摘要&#xff1a;机器视觉系统基本的特点就是提高生产的灵活性和自动化程度&#xff0c;目前机器视觉技术在蓬勃发展中&#xff0c;机器视觉尺寸测量仪是基于机器视觉原理制造而成的在线几何尺寸精密仪器。本文系统介绍一下该类测量设备。 机器视觉是什么&#xff1f; 简单来讲…

从0开始学习JavaScript--JavaScript数据类型与数据结构

JavaScript作为一门动态、弱类型的脚本语言&#xff0c;拥有丰富的数据类型和数据结构&#xff0c;这些构建了语言的基础&#xff0c;为开发者提供了灵活性和表达力。本文将深入探讨JavaScript中的各种数据类型&#xff0c;包括基本数据类型和复杂数据类型&#xff0c;并介绍常…

2023.11.24制作一个常用的登录注册模板(包含密码验证、输出格式验证、验证码等功能)

2023.11.24制作一个常用的登录注册模板&#xff08;包含密码验证、输出格式验证、验证码等功能&#xff09; 1. 简介2. 功能3. 页面效果3.1 登录页面3.2 忘记密码页3.3 注册页面 1. 简介 比较喜欢简洁风&#xff0c;只是用bootstrap进行简单装饰 制作一个模板&#xff0c;日常…

Leetcode---372周赛

题目列表 2937. 使三个字符串相等 2938. 区分黑球与白球 2939. 最大异或乘积 2940. 找到 Alice 和 Bob 可以相遇的建筑 一、使三个字符串相等 这题把题目意思读懂&#xff0c;正常模拟就行&#xff0c;简单来说就是看三个字符串的最长公共前缀有多长&#xff0c; 代码如下…

学习Pandas 二(Pandas缺失值处理、数据离散化、合并、交叉表与透视表、分组与聚合)

文章目录 六、高级处理-缺失值处理6.1 检查是否有缺失值6.2 缺失值处理6.3 不是缺失值NaN&#xff0c;有默认标记的 七、高级处理-数据离散化7.1 什么是数据的离散化7.2 为什么要离散化7.3 如何实现数据的离散化 八、高级处理-合并8.1 pc.concat实现合并&#xff0c;按方向进行…

x-www-form-urlencoded的含义解释,getReader()和getParameter()的区别

1、x-www-form-urlencoded x-www-form-urlencoded是一种编码格式&#xff0c;它是一种常见的编码方式&#xff0c;用于在HTTP请求中 传输表单数据 。在这种编码方式下&#xff0c;表单数据被编码为URL格式&#xff0c;然后作为请求体&#xff08;payload&#xff09;发送。 需要…

前端大厂(腾讯、字节跳动、阿里......)校招面试真题解析,让你面试轻松无压力!

前言 校招很重要&#xff0c;应届生的身份很珍贵&#xff01;在校招的时候与我们竞争的大部分都是没有工作经验的学生&#xff0c;而且校招企业对学生的包容度高&#xff0c;一般对企业来说&#xff0c;社招更看重实际工作经验&#xff0c;而校招更愿意“培养人”&#xff0c;校…

FindMy技术用于旅行箱

旅行箱&#xff0c;那是出门在外的我们不可或缺的伙伴。无论是商务出差&#xff0c;还是短途旅行&#xff0c;亦或是长途度假&#xff0c;旅行箱都以其便捷的方式&#xff0c;陪伴着我们的整个行程。 然而&#xff0c;在旅途中&#xff0c;丢失旅行箱是一件非常棘手的问题&…

【Web】PhpBypassTrick相关例题wp

目录 ①[NSSCTF 2022 Spring Recruit]babyphp ②[鹤城杯 2021]Middle magic ③[WUSTCTF 2020]朴实无华 ④[SWPUCTF 2022 新生赛]funny_php 明天中期考&#xff0c;先整理些小知识点冷静一下 ①[NSSCTF 2022 Spring Recruit]babyphp payload: a[]1&b1[]1&b2[]2&…

【计算机网络笔记】数据链路层——差错编码

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

RK3588平台 USB框架与USB识别流程

一.USB的基本概念 在最初的标准里&#xff0c;USB接头有4条线&#xff1a;电源&#xff0c;D-,D,地线。我们暂且把这样的叫做标准的USB接头吧。后来OTG出现了&#xff0c;又增加了miniUSB接头。而miniUSB接头则有5条线&#xff0c;多了一条ID线,用来标识身份用的。 热插拔&am…

VR全景展示,“超前点播”打开娱乐行业线上营销门户

如今&#xff0c;人们的生活水平正在逐步提高&#xff0c;这种提高不仅仅是体现在衣食住行上&#xff0c;更多方面是体现在大众的娱乐活动上。我们可以看到&#xff0c;相比于过去娱乐种类的匮乏&#xff0c;现如今&#xff0c;各种娱乐活动可谓是百家争鸣&#xff0c;例如温泉…

03.依赖倒置原则(Dependence Inversion Principle)

概述 高层模块不应依赖低层模块&#xff0c;二者都应该依赖其抽象。而抽象不应依赖细节&#xff0c;细节应该依赖抽象。依赖倒置原则的中心思想其实就是面向接口编程。 相对于细节的多变性&#xff0c;抽象的东西会稳定的多&#xff0c;所以以抽象为基础搭建的架构自然也会比以…

最新Midjourney绘画提示词Prompt教程无需魔法

最新Midjourney绘画提示词Prompt教程无需魔法使用 一、AI绘画工具 SparkAi【无需魔法使用】&#xff1a; SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧&#xff01;本系统使用NestjsVueTypes…

App 设计工具

目录 说明 打开 App 设计工具 示例 创建 App 创建自定义 UI 组件 打开现有 App 文件 打包和共享 App 本文主要讲述以交互方式创建 App。 说明 App 设计工具是一个交互式开发环境&#xff0c;用于设计 App 布局并对其行为进行编程。 可以使用 App 设计工具&#xff1a…

Python---函数的参数类型

位置参数 理论上&#xff0c;在函数定义时&#xff0c;我们可以为其定义多个参数。但是在函数调用时&#xff0c;我们也应该传递多个参数&#xff0c;正常情况&#xff0c;其要一一对应。 相关链接&#xff1a;Python---函数的作用&#xff0c;定义&#xff0c;使用步骤&…

1、postman的安装及使用

一、安装、登录 1.安装 下载地址 2.注册登录&#xff08;保存云服务进度&#xff09; 二、界面介绍 三、执行接口测试页面 请求页签&#xff1a; 1、params&#xff1a;当是get请求时&#xff0c;通过params传参 2、authorization&#xff1a;鉴权 3、headers&#xff1…

Ps:画笔工具的基本操作

画笔工具 Brush Tool是 Ps 中最常用的工具&#xff0c;广泛地用于绘画与修饰工作。 虽然多数操作可在画笔工具的工具选项栏中选择执行&#xff0c;但是如果能记住相应的快捷键可大大提高工作效率。 熟练掌握画笔工具的操作对于使用其他工具也非常有益&#xff0c;因为 Ps 中许多…