【LeetCode算法系列题解】第1~5题

news2024/11/20 20:35:48

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/955127.html

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

相关文章

文献综述|针对图像描述模型的对抗样本攻击

前言&#xff1a;图像描述对抗攻击旨在通过攻击正常的图像描述模型&#xff0c;为正常输入图像添加扰动得到对抗样本&#xff0c;使得正常模型输出目标句子或目标关键词&#xff0c;现将当前相关工作大致汇总如下。本综述初写于2022年8月29日。 部分相关工作介绍 Shekhar 等在…

【使用DataEase数据可视化分析工具访问cpolar】

DataEase 是开源的数据可视化分析工具&#xff0c;帮助用户快速分析数据并洞察业务趋势&#xff0c;从而实现业务的改进与优化。是开源的数据可视化分析工具&#xff0c;帮助用户快速分析数据并洞察业务趋势&#xff0c;从而实现业务的改进与优化。 在本地搭建后,借助cpolar 内…

阿里云国际站不想自己充值怎么办?-unirech阿里云国际站代充

在阿里云国际版官网注册是需要绑定paypal或者visa卡才可以完成注册&#xff0c;但是很多网友表示没有这些&#xff0c;阿里云国际站不想自己充值怎么办&#xff1f;其实通过分销商Unirech来注册的话就完全不用担心这个问题了&#xff0c;因为可以直接省略这一步&#xff0c;阿里…

【Java从入门到大牛】IO流下篇

&#x1f525; 本文由 程序喵正在路上 原创&#xff0c;CSDN首发&#xff01; &#x1f496; 系列专栏&#xff1a;Java从入门到大牛 &#x1f320; 首发时间&#xff1a;2023年8月31日 &#x1f98b; 欢迎关注&#x1f5b1;点赞&#x1f44d;收藏&#x1f31f;留言&#x1f43…

RT-Thread自动初始化机制

自动初始化机制是指初始化函数不需要被显示调用&#xff0c;只需要在函数定义处通过宏定义的方式进行申明&#xff0c;就会在系统启动过程中被执行。 int rt_hw_usart_init(void) {rt_hw_serial_register(&serial1, "uart1",RT_DEVICE_FLAG_RDWR | RT_DEVICE_FL…

Web服务器简介及HTTP协议

一、HTPP请求/响应报文格式 1.客户端连接到Web服务器 一个HTTP客户端&#xff0c;通常是浏览器&#xff0c;与Web服务器的HTTP端口&#xff08;默认为80&#xff09;建立一个TCP套接字连接。例如&#xff0c;http://www.baidu.com(URL) 2.发送HTTP请求 通过TCP套接字&#xff…

C++哈希(散列)与unordered关联式容器封装(Map、Set)

一、unordered系列关联式容器 在C98中&#xff0c;STL提供了以红黑树为底层数据结构的关联式容器&#xff08;map、set等&#xff09;&#xff0c;查询时的效率可以达到,最差情况下需要比较红黑树的高度次。因此在C11中&#xff0c;STL提供了四个unordered系列关联式容器&…

centos7 docker安装记录

以下所有命令都在root用户下进行&#xff0c;若为普通用户&#xff0c;需要在所有命令前加上 sudo。 1、更新yum包 将yum包更新到最新 yum update2、安装需要的软件包 yum-util 提供yum-config-manager功能&#xff0c;另外两个是devicemapper驱动依赖的&#xff1b; yum …

中国移动加大布局长三角,打造算力产业新高地

8月27日&#xff0c;以“数实融合算启未来”为主题的2023长三角算力发展大会在苏州举办&#xff0c;大会启动了长三角算力调度枢纽&#xff0c;携手各界推动算力产业高质量发展。 会上&#xff0c;移动云作为第一批算力资源提供方&#xff0c;与苏州市公共算力服务平台签订算力…

机器人编程怎么入门?

机器人已经在我们中间存在了二三十年。如今&#xff0c;机器人在我们的文化中比以往任何时候都更加根深蒂固。大多数机器人机器用于各种装配线&#xff0c;或在世界各地的矿山或工业设施中执行密集的物理操作。 还有一些家用机器人&#xff0c;工程师正在对机器人进行编程&…

debug调试时,通过[[FunctionLocation]]找到函数在源代码中的位置

[[FunctionLocation]] 是 JavaScript 引擎内部的一个属性&#xff0c;用于记录函数在代码中的位置。它不是 JavaScript 语法的一部分&#xff0c;而是在调试和开发过程中用于追踪函数定义位置的一个辅助属性。 当我们在浏览器的开发者工具或其他调试工具中查看函数的属性时&am…

【C++】Visual Studio EditorConfig 格式设置

【C】Visual Studio EditorConfig 格式设置 文章目录 【C】Visual Studio EditorConfig 格式设置I - EditorConfig1.1 - 通用设置indent_styleindent_sizetab_widthend_of_linecharsettrim_trailing_whitespaceinsert_final_newline II - Visual Studio 特定键值缩进设置cpp_in…

Docker基础入门:Docker网络与微服务项目发布

Docker基础入门&#xff1a;Docker网络与微服务项目发布 一、前言二、Docker0理解2.1 ip a查看当前网络环境2.2 实战--启动一个tomact01容器&#xff08;查看网络环境&#xff09;2.3 实战--启动一个tomact02容器&#xff08;查看网络环境&#xff09;2.4 容器与容器之间的通信…

企业数据将作为资产被纳入财务报表?百望云建议企业做好三点准备

在数字化转型过程中&#xff0c;大家一直比较关心技术创新有哪些&#xff0c;我如何能快速使用&#xff1f;却经常忽略了更深层次的问题&#xff0c;如&#xff1a;数字化转型的价值效益“有哪些”、我的企业“怎么获取”、我的系统是否支持“价值传递”&#xff1f; 近日&…

Apipost:为什么是开发者首选的API调试工具

文章目录 前言正文接口调试接口公共参数、环境全局参数的使用快速生成并导出接口文档研发协作接口压测和自动化测试结论 前言 Apipost是一款支持 RESTful API、SOAP API、GraphQL API等多种API类型&#xff0c;支持 HTTPS、WebSocket、gRPC多种通信协议的API调试工具。除此之外…

不知道怎么归类的题型

爆破 weak_auth 进来看到 随便输入 知道账号名为admin&#xff0c;再爆破密码&#xff0c;从返回包中得到flag

【C++】多态学习

多态 多态的概念与定义多态的概念构成多态的两个条件虚函数与重写重写的两个特例 final 和 override重载、重写(覆盖)、重定义(隐藏)的对比抽象类多态的原理静态绑定与动态绑定 单继承与多继承关系下的虚函数表(派生类)单继承中的虚函数表查看多继承中的虚函数表查看 菱形继承与…

JavaScript Web APIs -03 事件流、事件委托、其他事件(加载、滚动、尺寸)

Web APIs - 03 文章目录 Web APIs - 03事件流捕获和冒泡阻止冒泡 事件委托其他事件页面加载事件元素滚动事件页面尺寸事件 元素尺寸与位置 进一步学习 事件进阶&#xff0c;实现更多交互的网页特效&#xff0c;结合事件流的特征优化事件执行的效率 掌握阻止事件冒泡的方法理解事…

第五章 树与二叉树 四、线索树(手算与代码实现)

一、定义 1.线索树是一种二叉树&#xff0c;它在每个节点上增加了两个指针&#xff0c;分别指向其前驱和后继。 2.这些指针称为“线索”&#xff0c;因此线索树也叫做“线索化二叉树”。 3.在线索树中&#xff0c;所有的叶子节点都被线索化&#xff0c;使得遍历树的过程可以…

小程序实现图片上传、数量配置、预览、删除功能的开发指南

当谈到在小程序中实现图片上传、预览和删除等功能时,我们必须认识到这些功能对于提升用户体验和丰富应用的交互性非常关键。随着智能手机的普及,人们越来越习惯于通过图片来表达自己的想法、分享生活点滴,因此,使用户能够方便地在小程序中处理图片是非常重要的一步。 目录 …