LeetCode第1~5题解

news2024/11/19 5:53:14

CONTENTS

    • LeetCode 1. 两数之和(简单)
    • LeetCode 2. 两数相加(中等)
    • LeetCode 3. 无重复字符的最长子串(中等)
    • LeetCode 4. 寻找两个正序数组的中位数(困难)
    • LeetCode 5. 最长回文子串(中等)

LeetCode 1. 两数之和(简单)

【题目描述】

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。

【示例1】

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

【示例2】

输入:nums = [3,2,4], target = 6
输出:[1,2]

【示例3】

输入:nums = [3,3], target = 6
输出:[0,1]

【提示】

2 ≤ n u m s . l e n g t h ≤ 1 0 4 2\le nums.length\le 10^4 2nums.length104
− 1 0 9 ≤ n u m s [ i ] ≤ 1 0 9 -10^9\le nums[i]\le 10^9 109nums[i]109
− 1 0 9 ≤ t a r g e t ≤ 1 0 9 -10^9\le target\le 10^9 109target109

【分析】


维护一个哈希表,记录 n u m s [ 1 ] ∼ n u m s [ i − 1 ] nums[1]\sim nums[i-1] nums[1]nums[i1],当遍历到 n u m s [ i ] nums[i] nums[i] 时,通过哈希表查找是否存在 t a r g e t − n u m s [ i ] target-nums[i] targetnums[i],如果存在说明找到答案。


【代码】

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> st;
        for (int i = 0; i < nums.size(); i++)
        {
            int x = target - nums[i];
            if (st.count(x)) return { st[x], i };
            st[nums[i]] = i;
        }
        return {};  // 为了防止编译出问题
    }
};

LeetCode 2. 两数相加(中等)

【题目描述】

给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 0 0 之外,这两个数都不会以 0 0 0 开头。

【示例1】

在这里插入图片描述

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

【示例2】

输入:l1 = [0], l2 = [0]
输出:[0]

【示例3】

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

【提示】

每个链表中的节点数在范围 [ 1 , 100 ] [1, 100] [1,100]
0 ≤ N o d e . v a l ≤ 9 0\le Node.val\le 9 0Node.val9
题目数据保证列表表示的数字不含前导零

【分析】


模拟题,遍历两个链表,按照高精度加法的思想逐位相加,直到遍历完两个链表且没有进位即可。构造结果链表时可以先创建一个虚拟头结点,返回的时候返回虚拟头结点的下一个结点即可。


【代码】

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        auto dummy = new ListNode(-1), cur = dummy;  // 虚拟头结点,cur表示当前指向的结点
        int t = 0;  // 进位
        while (l1 || l2 || t)
        {
            if (l1) t += l1->val, l1 = l1->next;
            if (l2) t += l2->val, l2 = l2->next;
            cur = cur->next = new ListNode(t % 10);  // 记得要更新cur指向下一个结点
            t /= 10;
        }
        return dummy->next;
    }
};

LeetCode 3. 无重复字符的最长子串(中等)

【题目描述】

给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度。

【示例1】

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

【示例2】

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

【示例3】

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是子串的长度,"pwke" 是一个子序列,不是子串。

【提示】

0 ≤ s . l e n g t h ≤ 5 ∗ 1 0 4 0\le s.length\le 5*10^4 0s.length5104
s 由英文字母、数字、符号和空格组成

【分析】


我们枚举所有以 i i i 为尾端点的子串,分别找出最长的不包含重复字符的子串。因此对于每个 i i i,我们需要找到一个最靠左端点的 j j j,使得 j ∼ i j\sim i ji 中不包含重复的字符。现在再假设 i i i 向右移动到 i ′ i' i,显然其对应的 j ′ j' j 一定大于等于 j j j,否则通过反证法, j ′ j' j j j j 的左边且 j ′ ∼ i ′ j'\sim i' ji 中不包含重复的字符,那么 j ′ ∼ i j'\sim i ji 中一定也不包含重复的字符。

综上,我们在枚举 i i i 的时候同样也只需要枚举一遍 j j j,而不需要重复枚举。


【代码】

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char, int> st;
        int res = 0;
        for (int i = 0, j = 0; i < s.size(); i++)
        {
            st[s[i]]++;
            while (st[s[i]] > 1) st[s[j++]]--;  // 当j==i时s[i]一定只出现一次了
            res = max(res, i - j + 1);
        }
        return res;
    }
};

LeetCode 4. 寻找两个正序数组的中位数(困难)

【题目描述】

给定两个大小分别为 mn 的正序(从小到大)数组 nums1nums2。请你找出并返回这两个正序数组的中位数
算法的时间复杂度应该为 O ( l o g ( m + n ) ) O(log(m+n)) O(log(m+n))

【示例1】

输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2

【示例2】

输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5

【提示】

n u m s 1. l e n g t h = = m nums1.length == m nums1.length==m
n u m s 2. l e n g t h = = n nums2.length == n nums2.length==n
0 ≤ m ≤ 1000 0\le m\le 1000 0m1000
0 ≤ n ≤ 1000 0\le n\le 1000 0n1000
1 ≤ m + n ≤ 2000 1\le m + n\le 2000 1m+n2000
− 1 0 6 ≤ n u m s 1 [ i ] , n u m s 2 [ i ] ≤ 1 0 6 -10^6\le nums1[i], nums2[i]\le 10^6 106nums1[i],nums2[i]106

【分析】


我们求出这两个有序数组中从小到大排第 k k k 个数是多少即可解决这个问题,当 k = n + m 2 k=\frac {n+m}{2} k=2n+m 时就是答案。

要解决这个问题我们可以把它分解成子问题,首先我们先分别在这两个数组(记为 A A A B B B)找到第 k 2 \frac {k}{2} 2k 大的数 A [ k 2 ] A[\frac {k}{2}] A[2k] B [ k 2 ] B[\frac {k}{2}] B[2k],然后我们分以下三种情况进行讨论:

  • A [ k 2 ] < B [ k 2 ] A[\frac {k}{2}] < B[\frac {k}{2}] A[2k]<B[2k]:在 A A A 中小于等于 A [ k 2 ] A[\frac {k}{2}] A[2k] 的数有 k 2 \frac {k}{2} 2k 个,因为 B [ k 2 ] B[\frac {k}{2}] B[2k] 严格大于 A [ k 2 ] A[\frac {k}{2}] A[2k],因此在 B B B 中小于等于 A [ k 2 ] A[\frac {k}{2}] A[2k] 的数肯定不足 k 2 \frac {k}{2} 2k 个。那么小于等于 A [ k 2 ] A[\frac {k}{2}] A[2k] 的数的数量一定小于 k k k,即 A [ 1 ∼ k 2 ] A[1\sim \frac {k}{2}] A[12k] 一定不会是答案,就可以把这一部分删掉。
  • A [ k 2 ] > B [ k 2 ] A[\frac {k}{2}] > B[\frac {k}{2}] A[2k]>B[2k]:与第一种情况类似,小于等于 B [ k 2 ] B[\frac {k}{2}] B[2k] 的数的数量一定小于 k k k,即 B [ 1 ∼ k 2 ] B[1\sim \frac {k}{2}] B[12k] 一定不会是答案,就可以把这一部分删掉。
  • A [ k 2 ] = B [ k 2 ] A[\frac {k}{2}] = B[\frac {k}{2}] A[2k]=B[2k]:这种情况下 A [ k 2 ] A[\frac {k}{2}] A[2k] B [ k 2 ] B[\frac {k}{2}] B[2k] 都可以作为答案,它们都是第 k k k 大的数,但是由于 [ k 2 [\frac {k}{2} [2k 有可能会比较短的那个数组长度更大,因此不能保证每次两个数组都能取到 [ k 2 [\frac {k}{2} [2k 处,此时随便删去任意一段就行。

综上,我们每次都可以删去 k 2 \frac {k}{2} 2k 个数,例如第一轮删去 A [ 1 ∼ k 2 ] A[1\sim \frac {k}{2}] A[12k] 后相当于在 A [ k 2 + 1 ∼ m ] A[\frac {k}{2}+1\sim m] A[2k+1m] B [ 1 ∼ n ] B[1\sim n] B[1n] 中找第 k − k 2 k-\frac {k}{2} k2k 个数。当 k = 1 k=1 k=1 时即找两个数组的最小值即可。


【代码】

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int cnt = nums1.size() + nums2.size();
        if (cnt % 2 == 0)  // 长度为偶数时中位数为中间两个数的平均值
        {
            int l = find(nums1, 0, nums2, 0, cnt / 2);
            int r = find(nums1, 0, nums2, 0, cnt / 2 + 1);
            return (l + r) / 2.0;  // 注意浮点除法
        }
        else return find(nums1, 0, nums2, 0, cnt / 2 + 1);
    }

    // 从nums1的第i个位置以及nums2的第j个位置开始找第k个数
    int find(vector<int>& nums1, int i, vector<int>& nums2, int j, int k)
    {
        // 统一当做nums1是较短的数组来处理
        if (nums1.size() - i > nums2.size() - j) return find(nums2, j, nums1, i, k);
        if (i == nums1.size()) return nums2[j + k - 1];  // nums1为空
        if (k == 1) return min(nums1[i], nums2[j]);
        int a = min(int(nums1.size()), i + k / 2), b = j + (k - k / 2);  // 较短的数组取k/2可能越界
        if (nums1[a - 1] < nums2[b - 1])  // 第一种情况
            return find(nums1, a, nums2, j, k - (a - i));
        else  // 第二和第三种情况
            return find(nums1, i, nums2, b, k - (b - j));
    }
};

LeetCode 5. 最长回文子串(中等)

【题目描述】

给你一个字符串 s,找到 s 中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

【示例1】

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

【示例2】

输入:s = "cbbd"
输出:"bb"

【提示】

1 ≤ s . l e n g t h ≤ 1000 1\le s.length\le 1000 1s.length1000
s 仅由数字和英文字母组成

【分析】


关于最长回文子串的问题有多种解法,最优解法为 Manacher 算法,不过此处不做介绍。

我们枚举回文串的中心点,对于每个中心点设置两个指针分别往左和往右走,找出最长的满足回文的子串,然后维护一个全局最优解即可。


【代码】

class Solution {
public:
    string longestPalindrome(string s) {
        string res;
        for (int i = 0; i < s.size(); i++)
        {
            int l = i - 1, r = i + 1;  // 长度为奇数的情况
            while (l >= 0 && r < s.size() && s[l] == s[r]) l--, r++;
            if (res.size() < r - l - 1) res = s.substr(l + 1, r - l - 1);
            l = i, r = i + 1;  // 长度为偶数的情况
            while (l >= 0 && r < s.size() && s[l] == s[r]) l--, r++;
            if (res.size() < r - l - 1) res = s.substr(l + 1, r - l - 1);
        }
        return res;
    }
};

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

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

相关文章

【awd系列】Bugku S3 AWD排位赛-9 pwn类型

文章目录 二进制下载检查分析运行二进制ida分析解题思路exp 二进制下载 下载地址&#xff1a;传送门 检查分析 [rootningan 3rd]# file pwn pwn: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for …

android系统启动流程之SystemServer运行过程

SystemServer进程的启动流程&#xff1a;直接看代码&#xff1a; SystemServer是Java中的一个进程&#xff0c;执行入口是SystemServer.java.main(); SystemServer.java.main();-->new SystemServer().run();-->createSystemContext();//创建系统上下文:虽然SystemServe…

Unittest 笔记:unittest拓展生成HTM报告发送邮件

HTMLTestRunner 是一个unitest拓展可以生成HTML 报告 下载地址&#xff1a;GitHub: https://github.com/defnnig/HTMLTestRunner HTMLTestRunner是一个独立的py文件&#xff0c;可以放在Lib 作为第三方模块使用或者作为项目的一部分。 方式1&#xff1a; 验证是否安装成功&…

Flutter 状态管理引子

1、为了更好地了解状态管理&#xff0c;先看看什么是状态。 在类似Flutter这样的响应式编程框架中&#xff0c;我们可以认为U相关的开发就是对数据进行封装&#xff0c;将之转换为具体的U1布局或者组件。借用Flutter官网的一张图&#xff0c;可以把我们在第二部分做的所有开发…

AliOS-Things引入

目录 一、简介 1.1 硬件抽象层 1.2 AliOS-Things内核 rhino ​编辑 1.3 AliOS-Things组件 二、如何进行AliOS-Things开发 三、安装环境 安装python pip git 修改pip镜像源 安装aos-cube 一、简介 AliOS-Things是阿里巴巴公司推出的致力于搭建云端一体化LoT软件。AliOS-…

Linux操作系统--文件与目录结构

我们初步认识了Linux操作系统,下面我们进一步看看linux的文件与目录结构。 1.文件系统和挂载点 (1).当前的操作系统中查看文件系统 位置 > 计算机 这样你就可以看见当前操作系统中的所有目录和文件。如下所示: (2).挂载点 挂载点实际上就是linux中的磁盘文件系统的入口…

快速理解 X server, DISPLAY 与 X11 Forwarding

​ X server X server是X Window System &#xff08;简称X11或者X&#xff09;系统中的显示服务器&#xff08;display server&#xff09;&#xff0c;用于监听X client发送来的图形界面显示请求&#xff0c;并且将图形界面绘制并显示在屏幕&#xff08;screen&#xff09;…

粒子群算法的基本原理和Matlab实现

1.案例背景 1.1 PSO算法介绍 粒子群优化算法(Particle Swarm Optimization,PSO)是计算智能领域,除了蚁群算法,鱼群算法之外的一种群体智能的优化算法,该算法最早是由Kennedy和 Eberhart 在1995年提出的。PSO算法源于对鸟类捕食行为的研究,鸟类捕食时,每只鸟找到食物最简单有效…

webassembly003 ggml GGML Tensor Library part-3

关于pthread_create()和pthread_join() #include <stdio.h> #include <pthread.h>void *thread_func(void *arg) {int *num (int *)arg;printf("Hello from thread! arg%d\n", *num);pthread_exit(NULL); }int main() {pthread_t thread;int arg 10;i…

解锁开发中的创意:用户为中心的设计思维的力量

引言 设计思维&#xff0c;起源于20世纪60年代&#xff0c;是一种解决问题的方法。它不仅仅是设计师的专利&#xff0c;而是一种可以广泛应用于各种行业和领域的方法。设计思维强调了用户至中的重要性&#xff0c;认为任何问题的解决都应该从用户的需求出发。这种方法鼓励我们…

反转链表+交换两个链表的节点

目录 ​编辑 一&#xff0c;反转链表 1.题目描述 2.例子 3.题目接口 4.分析以及解题代码 1.迭代法 2.递归写法 二&#xff0c;两两交换两个链表中的节点 1.题目描述 2.例子 3.题目接口 4.题目分析以及解法 一&#xff0c;反转链表 1.题目描述 首先来看看反转链表的…

主流深度学习框架及神经网络模型汇总

目录 主流深度学习框架及神经网络模型汇总 一、人工智能的研究领域和分支 二、主流深度学习框架​编辑 1.TensorFlow 2.PyTorch 3.PaddlePaddle 4.Keras 5.Caffe/Caffe2 6.MXNet 7.Theano 8.Torch 9.CNTK 10.ONNX 三、深度学习移动端推理框架 1.TensorRT 2.TF-…

LabVIEW是如何控制硬件的?

概述 工程 师 和 科学 家 可以 使用 LabVIEW 与 数千 种 不同 的 硬件 设备 无缝 集成&#xff0c; 并 通过 方便 的 功能 和 跨 所有 硬件 的 一致 编 程 框架 帮助 节省 开发 时间。 内容 通过更简单的系统集成节省开发时间 连接到任何硬件 NI 硬件 第三方硬件 快速找到…

数据库事务四大特性

事务的4大特性&#xff08;ACID&#xff09;&#xff1a; 原子性(Atomicity)&#xff1a; 事务是数据库的逻辑工作单位&#xff0c;它对数据库的修改要么全部执行&#xff0c;要么全部不执行。 一致性(Consistemcy)&#xff1a; 事务前后&#xff0c;数据库的状态都满足所有的完…

Python之defaultdict方法详解

文章目录 字典dict介绍collections.defaultdict类 字典dict介绍 python中的dict是一个重要的数据类型,用“键”(key)来索引&#xff0c;表示为dict(key: val, …),有以下特征&#xff1a; 键可以是任何不可变(immutable)数据类型不可变数据类型有&#xff1a;数字&#xff0c…

嵌入式软件设计

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

手写数字识别之损失函数

目录 交叉熵 手写数字识别之损失函数 分类任务的损失函数 Softmax函数 交叉熵的简单理解&#xff1a;真实分布与非真实分布的交叉&#xff0c;完全对应&#xff0c;熵为0 交叉熵的代码实现 交叉熵 给定一个策略, 交叉熵就是在该策略下猜中颜色所需要的问题的期望值。更普…

三、JVM监控及诊断工具-GUI篇

目录 一、工具概述二、jconsole&#xff08;了解即可&#xff09;1、基本概述2、启动3、三种连接方式4、作用 三、Visual VM 一、工具概述 二、jconsole&#xff08;了解即可&#xff09; 1、基本概述 从Java5开始&#xff0c;在JDK中自带的Java监控和管理控制台用于对JVM中内…

【mindspore学习】环境配置

本次实验搭配的环境是 CUDA 11.6 CUDNN v8.9.4 TensorRT-8.4.1.5 mindspore 2.1.0。 1、配置 Nvidia 显卡驱动 如果原来的主机已经安装了 nvidia 驱动&#xff0c;为避免版本的冲突&#xff0c;建议先清除掉旧的 nvidia驱动 sudo apt-get --purge remove nvidia* sudo apt…

土豆叶病害识别(图像连续识别和视频识别)

效果视频&#xff1a;土豆叶病害识别&#xff08;Python代码&#xff0c;pyTorch框架&#xff0c;视频识别&#xff09;_哔哩哔哩_bilibili 代码运行要求&#xff1a;Torch库>1.13.1&#xff0c;其它库无版本要求 1..土豆叶数据集主要包好三种类别&#xff08;Early_Blight…