0%

AcWing LeetCode究极班 Week1

学习平台

AcWing LeetCode究极班

LeetCode

Let 1:两数之和

给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • 2 <= nums.length <= 104
  • 109 <= nums[i] <= 109
  • 109 <= target <= 109
  • 只会存在一个有效答案

进阶:你可以想出一个时间复杂度小于 O(n^2) 的算法吗?

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> arr;
for(int i=0;i < nums.size() - 1; i++){
for(int j = i + 1;j< nums.size(); j++){
if(nums[i]+nums[j] == target){
arr.push_back(i);
arr.push_back(j);
break;
}
}
}
return arr;
}
};

Let 2:两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1:

img

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

示例 2:

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

示例 3:

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

提示:

  • 每个链表中的节点数在范围 [1, 100]
  • 0 <= Node.val <= 9
  • 题目数据保证列表表示的数字不含前导零

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 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); // 生成一个新的头节点,指向结果
auto cur = dummy; // 一个指针,指向结果链表的尾节点
int t = 0; //用来保存进位
while(l1 || l2 || t){
if(l1) t += l1 -> val, l1 = l1 -> next;
if(l2) t += l2 -> val, l2 = l2 -> next;
cur -> next = new ListNode(t % 10); // 取出个位加入生成新节点
cur = cur -> next; // 更新尾指针
t /= 10; // 去除进位
}
return dummy -> next;
}
};

Let 3:无重复字符的最长子串

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

示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • 0 <= s.length <= 5 * 104
  • s由英文字母、数字、符号和空格组成

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> head; // hash map
int res = 0;
for(int i = 0, j = 0; i < s.length(); i ++){
head[s[i]]++;
while(head[s[i]] > 1) head[s[j++]]--;
res = max(res, i - j + 1);
}
return res;
}
};

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

给定两个大小分别为 mn 的正序(从小到大)数组 nums1nums2。请你找出并返回这两个正序数组的 中位数

算法的时间复杂度应该为 O(log (m+n))

示例 1:

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

示例 2:

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

提示:

  • nums1.length == m
  • nums2.length == n
  • 0 <= m <= 1000
  • 0 <= n <= 1000
  • 1 <= m + n <= 2000
  • -106 <= nums1[i], nums2[i] <= 106

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
vector<double> arr; // 将两个数组合并后的数组
int i = 0, j = 0;
while(i < nums1.size() && j < nums2.size()){
if(nums1[i] <= nums2[j])
arr.push_back(nums1[i++]);
else
arr.push_back(nums2[j++]);
}
while(i < nums1.size()) arr.push_back(nums1[i++]);
while(j < nums2.size()) arr.push_back(nums2[j++]);

int len = arr.size();
for(int k = 0; k < arr.size(); k++) cout << arr[k] << " ";
if(len % 2 != 0){ // 合并后的数组长度是奇数
return arr[len / 2];
}
else{ // 合并后的数组长度是偶数
return (arr[len / 2] + arr[len / 2 - 1]) / 2;
}
}
};

Let 5:最长回文子串 *

给你一个字符串 s,找到 s 中最长的回文子串。

示例 1:

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

示例 2:

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

提示:

  • 1 <= s.length <= 1000
  • s 仅由数字和英文字母组成

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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;
}
};

Let 6:Z 字形变换

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:

1
2
3
P   A   H   N
A P L S I I G
Y I R

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"

请你实现这个将字符串进行指定行数变换的函数:

1
string convert(string s, int numRows);

示例 1:

1
2
输入:s = "PAYPALISHIRING", numRows = 3
输出:"PAHNAPLSIIGYIR"

示例 2:

1
2
3
4
5
6
7
输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
解释:
P I N
A L S I G
Y A H R
P I

示例 3:

1
2
输入:s = "A", numRows = 1
输出:"A"

提示:

  • 1 <= s.length <= 1000
  • s 由英文字母(小写和大写)、',''.' 组成
  • 1 <= numRows <= 1000

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
string convert(string s, int n) {
string res;
if (n == 1) return s;
for (int i = 0; i < n; i ++ ) {
if (i == 0 || i == n - 1) {
for (int j = i; j < s.size(); j += 2 * n - 2)
res += s[j];
} else {
for (int j = i, k = 2 * n - 2 - i; j < s.size() || k < s.size(); j += 2 * n - 2, k += 2 * n - 2) {
if (j < s.size()) res += s[j];
if (k < s.size()) res += s[k];
}
}
}
return res;
}
};

Let 7:整数反转

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。

如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。

假设环境不允许存储 64 位整数(有符号或无符号)。

示例 1:

1
2
输入:x = 123
输出:321

示例 2:

1
2
输入:x = -123
输出:-321

示例 3:

1
2
输入:x = 120
输出:21

示例 4:

1
2
输入:x = 0
输出:0

提示:

  • -231 <= x <= 231 - 1

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public:
int reverse(int x) {
if(x >= -9 && x <= 9) return x;
long long ans = 0;
while(x){
ans = ans * 10 + x % 10;
if(ans < -2147483648 || ans > 2147483647){
return 0;
}
x /= 10;
}

return ans;
}
};

Let 8:字符串转换整数(atoi) *

请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。

函数 myAtoi(string s) 的算法如下:

  1. 读入字符串并丢弃无用的前导空格
  2. 检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
  3. 读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
  4. 将前面步骤读入的这些数字转换为整数(即,”123” -> 123, “0032” -> 32)。如果没有读入数字,则整数为0 。必要时更改符号(从步骤 2 开始)。
  5. 如果整数数超过 32 位有符号整数范围 [−231, 231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −231,大于 231 − 1 的整数应该被固定为 231 − 1
  6. 返回整数作为最终结果。

注意:

  • 本题中的空白字符只包括空格字符' '
  • 除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。

示例 1:

1
2
3
4
5
6
7
8
9
10
11
输入:s = "42"
输出:42
解释:加粗的字符串为已经读入的字符,插入符号是当前读取的字符。
第 1 步:"42"(当前没有读入字符,因为没有前导空格)
^
第 2 步:"42"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
^
第 3 步:"42"(读入 "42")
^
解析得到整数 42 。
由于 "42" 在范围 [-231, 231 - 1] 内,最终结果为 42 。

示例 2:

1
2
3
4
5
6
7
8
9
10
11
输入:s = "   -42"
输出:-42
解释:
第 1 步:" -42"(读入前导空格,但忽视掉)
^
第 2 步:" -42"(读入 '-' 字符,所以结果应该是负数)
^
第 3 步:" -42"(读入 "42")
^
解析得到整数 -42 。
由于 "-42" 在范围 [-231, 231 - 1] 内,最终结果为 -42 。

示例 3:

1
2
3
4
5
6
7
8
9
10
11
输入:s = "4193 with words"
输出:4193
解释:
第 1 步:"4193 with words"(当前没有读入字符,因为没有前导空格)
^
第 2 步:"4193 with words"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
^
第 3 步:"4193 with words"(读入 "4193";由于下一个字符不是一个数字,所以读入停止)
^
解析得到整数 4193 。
由于 "4193" 在范围 [-231, 231 - 1] 内,最终结果为 4193 。

提示:

  • 0 <= s.length <= 200
  • s 由英文字母(大写和小写)、数字(0-9)' ''+''-''.' 组成

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public:
int myAtoi(string s) {
int k = 0;
while(k < s.size() && s[k] == ' ') k++; //去掉前导空格

int minus = 1;
if(s[k] == '-') minus = -1, k++;
else if(s[k] == '+') k++;

int res = 0;
while(k < s.size() && s[k] >= '0' && s[k] <= '9'){
int x = s[k] - '0';
if(minus > 0 && res > (INT_MAX - x) / 10) return INT_MAX; //加上x后会超出上界
if(minus < 0 && -res < (INT_MIN + x) / 10) return INT_MIN; //加上x后会超出下界
if (-res * 10 - x == INT_MIN) return INT_MIN; //加上x刚好等于下界
res = res * 10 + x;
k++;
if(res > INT_MAX) break;
}
res *= minus;
return res;
}
};

Let 9:回文数

给你一个整数 x ,如果 x是一个回文整数,返回 true ;否则,返回 false

回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

  • 例如,121 是回文,而 123 不是。

示例 1:

1
2
输入:x = 121
输出:true

示例 2:

1
2
3
输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

示例 3:

1
2
3
输入:x = 10
输出:false
解释:从右向左读, 为 01 。因此它不是一个回文数。

提示:

  • -231 <= x <= 231 - 1

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public:
bool isPalindrome(int x) {
if(x < 0) return false;
int m = x;
long long ans = 0;
while(m){
ans = ans * 10 + m % 10;
m /= 10;
}
if(ans == x) return true;
return false;
}
};

Let 10:正则表达式匹配 *

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持'.''*' 的正则表达式匹配。

  • '.'匹配任意单个字符
  • '*' 匹配零个或多个前面的那一个元素

所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

示例 1:

1
2
3
输入:s = "aa", p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。

示例 2:

1
2
3
输入:s = "aa", p = "a*"
输出:true
解释:因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。

示例 3:

1
2
3
输入:s = "ab", p = ".*"
输出:true
解释:".*" 表示可匹配零个或多个('*')任意字符('.')。

提示:

  • 1 <= s.length <= 20
  • 1 <= p.length <= 30
  • s 只包含从 a-z 的小写字母。
  • p 只包含从 a-z 的小写字母,以及字符 .*
  • 保证每次出现字符*时,前面都匹配到有效的字符
正在加载今日诗词....