LeetCode刷题总结

本文是对LeetCode中部分算法题目的总结,包括两数之和、两数相加、无重复字符的最长子串等经典问题。文章介绍了各种解题方法,如哈希表、二分查找、滑动窗口等,并提供了相应的代码实现。
摘要由CSDN通过智能技术生成

LeetCode刷题小结

注:素材来源(LeetCode)
1. 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
解法:
1.暴力二重循环,时间复杂度O(n^2),空间复杂度O(1)
2. hash map加循环 时间复杂度O(n),空间复杂度O(n)

2. 两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
解法:.循环+进位标记,时间复杂度O(max(m,n)),空间负责度O(max(m,n))

3. 无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
解法:
1.滑动窗口 使用两个指针表示字符串中的某个子串(的左右边界)。其中左指针代表着上文中「枚举子串的起始位置」,而右指针即为上文中的 r_kr k在每一步的操作中,我们会将左指针向右移动一格,表示 我们开始枚举下一个字符作为起始位置,然后我们可以不断地向右移动右指针,但需要保证这两个指针对应的子串中没有重复的字符。在移动结束后,这个子串就对应着 以左指针开始的,不包含重复字符的最长子串。我们记录下这个子串的长度;在枚举结束后,我们找到的最长的子串的长度即为答案
2. hash map加循环 时间复杂度O(n),空间复杂度O(n)

4. 寻找两个正序数组的中位数

给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数。进阶:你能设计一个时间复杂度为 O(log (m+n)) 的算法解决此问题吗?
解法:
1.二分查找
给定两个有序数组,要求找到两个有序数组的中位数,最直观的思路有以下两种:
使用归并的方式,合并两个有序数组,得到一个大的有序数组。大的有序数组的中间位置的元素,即为中位数。
不需要合并两个有序数组,只要找到中位数的位置即可。由于两个数组的长度已知,因此中位数对应的两个数组的下标之和也是已知的。维护两个指针,初始时分别指向两个数组的下标 00 的位置,每次将指向较小值的指针后移一位(如果一个指针已经到达数组末尾,则只需要移动另一个数组的指针),直到到达中位数的位置。
假设两个有序数组的长度分别为 mm 和 nn,上述两种思路的复杂度如何?
第一种思路的时间复杂度是 O(m+n)O(m+n),空间复杂度是 O(m+n)O(m+n)。第二种思路虽然可以将空间复杂度降到 O(1)O(1),但是时间复杂度仍是 O(m+n)O(m+n)。题目要求时间复杂度是 O(\log(m+n))O(log(m+n)),因此上述两种思路都不满足题目要求的时间复杂度。
如何把时间复杂度降低到 O(\log(m+n))O(log(m+n)) 呢?如果对时间复杂度的要求有 \loglog,通常都需要用到二分查找,这道题也可以通过二分查找实现。
根据中位数的定义,当 m+nm+n 是奇数时,中位数是两个有序数组中的第 (m+n)/2(m+n)/2 个元素,当 m+nm+n 是偶数时,中位数是两个有序数组中的第 (m+n)/2(m+n)/2 个元素和第 (m+n)/2+1(m+n)/2+1 个元素的平均值。因此,这道题可以转化成寻找两个有序数组中的第 kk 小的数,其中 kk 为 (m+n)/2(m+n)/2 或 (m+n)/2+1(m+n)/2+1。
假设两个有序数组分别是 \text{A}A 和 \text{B}B。要找到第 kk 个元素,我们可以比较 \text{A}[k/2-1]A[k/2−1] 和 \text{B}[k/2-1]B[k/2−1],其中 // 表示整数除法。由于 \text{A}[k/2-1]A[k/2−1] 和 \text{B}[k/2-1]B[k/2−1] 的前面分别有 \text{A}[0,…,k/2-2]A[0…k/2−2] 和 \text{B}[0,…,k/2-2]B[0…k/2−2],即 k/2-1k/2−1 个元素,对于 \text{A}[k/2-1]A[k/2−1] 和 \text{B}[k/2-1]B[k/2−1] 中的较小值,最多只会有 (k/2-1)+(k/2-1) \leq k-2(k/2−1)+(k/2−1)≤k−2 个元素比它小,那么它就不能是第 kk 小的数了。
因此我们可以归纳出三种情况:
如果 \text{A}[k/2-1] < \text{B}[k/2-1]A[k/2−1]<B[k/2−1],则比 \text{A}[k/2-1]A[k/2−1] 小的数最多只有 \text{A}A 的前 k/2-1k/2−1 个数和 \text{B}B 的前 k/2-1k/2−1 个数,即比 \text{A}[k/2-1]A[k/2−1] 小的数最多只有 k-2k−2 个,因此 \text{A}[k/2-1]A[k/2−1] 不可能是第 kk 个数,\text{A}[0]A[0] 到 \text{A}[k/2-1]A[k/2−1] 也都不可能是第 kk 个数,可以全部排除。
如果 \text{A}[k/2-1] > \text{B}[k/2-1]A[k/2−1]>B[k/2−1],则可以排除 \text{B}[0]B[0] 到 \text{B}[k/2-1]B[k/2−1]。
如果 \text{A}[k/2-1] = \text{B}[k/2-1]A[k/2−1]=B[k/2−1],则可以归入第一种情况处理。
可以看到,比较 \text{A}[k/2-1]A[k/2−1] 和 \text{B}[k/2-1]B[k/2−1] 之后,可以排除 k/2k/2 个不可能是第 kk 小的数,查找范围缩小了一半。同时,我们将在排除后的新数组上继续进行二分查找,并且根据我们排除数的个数,减少 kk 的值,这是因为我们排除的数都不大于第 kk 小的数。
有以下三种情况需要特殊处理:
如果 \text{A}[k/2-1]A[k/2−1] 或者 \text{B}[k/2-1]B[k/2−1] 越界,那么我们可以选取对应数组中的最后一个元素。在这种情况下,我们必须根据排除数的个数减少 kk 的值,而不能直接将 kk 减去 k/2k/2。
如果一个数组为空,说明该数组中的所有元素都被排除,我们可以直接返回另一个数组中第 kk 小的元素。
如果 k=1k=1,我们只要返回两个数组首元素的最小值即可。

5. 最长回文串

给你一个字符串 s,找到 s 中最长的回文子串。
解法:
1在这里插入图片描述
在这里插入图片描述

2.中心扩展算法在这里插入图片描述

6. Z字形变化

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时
方法一:按行排序
思路
通过从左向右迭代字符串,我们可以轻松地确定字符位于 Z 字形图案中的哪一行。
算法
我们可以使用 \text{min}( \text{numRows}, \text{len}(s))min(numRows,len(s)) 个列表来表示 Z 字形图案中的非空行。
从左到右迭代 ss,将每个字符添加到合适的行。可以使用当前行和当前方向这两个变量对合适的行进行跟踪。
只有当我们向上移动到最上面的行或向下移动到最下面的行时,当前方向才会发生改变。
在这里插入图片描述

7. 整数反转

给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
注意:
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
解法:
在这里插入图片描述

8. 字符串转换整数 atoi

请你来实现一个 atoi 函数,使其能将字符串转换成整数。
首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。接下来的转化规则如下:
如果第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字字符组合起来,形成一个有符号整数。
假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成一个整数。
该字符串在有效的整数部分之后也可能会存在多余的字符,那么这些字符可以被忽略,它们对函数不应该造成影响。
假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换,即无法进行有效转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0 。
注意:
本题中的空白字符只包括空格字符 ’ ’ 。
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231,

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值