前言
hello,小伙伴们大家好~ 我是雨墨,近期开始准备刷 leetcode ~ 故想将自己的刷题笔记以博客的形式分享出来,这是我的第一篇博客,小伙伴们可以在评论区讨论和点赞哟~~
仅以此篇博文记录自己刷数组经典题的过程,日后好复习,持续更新中,每日更新两三题,直到刷完规化好的数组题~
现已将计划刷的数组题刷完了,后续开始刷其他类型的题目~~~
leetcode 1 两数之和
1.1 题目链接
传送门:https://leetcode-cn.com/problems/two-sum/
1.2 我的题解
题目描述
给定一个数组和一个整数目标值,使得两个数之和等于目标值,题目保证一定有解,要求返回数组下标。
样例
给定数组 nums = [2,7,11,15], target = 9
由于 nums[0] + nums[1] = 2 + 7 = 9
所以 return [0, 1]
算法1
(暴力枚举) O ( n 2 ) O(n^2) O(n2)
暴力枚举方法:枚举下标 i , j i, j i,j,然后判断 n u m s [ i ] + n u m s [ j ] = = t a r g e t nums[i] + nums[j] == target nums[i]+nums[j]==target
时间复杂度:由于是两重循环,所以时间复杂度是 O ( n 2 ) O(n^2) O(n2)
C++代码
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
for (int i = 0; i < nums.size(); ++i) {
for (int j = i + 1; j < nums.size(); ++j) {
if (nums[i] + nums[j] == target)
return {
i, j};
}
}
return {
};
}
};
算法2:
(哈希表) O ( n ) O(n) O(n)
使用C++中的哈希表——unrodered_map<int, int> hash
循环一遍 n u m s nums nums数组,在每一步循环中做两件事:
- 判断 t a r g e t − n u m s [ i ] target - nums[i] target−nums[i]是否在哈希表中;
- 将会 n u m s [ i ] nums[i] nums[i]插入到哈希表中;
解释:由于数据保证有且仅有一组解,假设是 [ i , j ] ( i < j ) [i, j](i < j) [i,j](i<j),则我们循环到 j j j时, n u m s [ i ] nums[i] nums[i]一定在哈希表中,且有 n u m s [ i ] + n u m s [ j ] = = t a r g e t nums[i] + nums[j] == target nums[i]+nums[j]==target,所以我们一定能找到解。
时间复杂度:由于只扫描一遍,每次哈希表的查找和插入操作的复杂度是 O ( 1 ) O(1) O(1),所以时间复杂度是 O ( n ) O(n) O(n)
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> hash;
for (int i = 0; i < nums.size(); ++i) {
int j = target - nums[i];
if (hash.count(j)) return {
hash[j], i};
hash[nums[i]] = i;
}
return {
};
}
};
leetcode 54 螺旋矩阵
2.1 题目链接
传送门:https://leetcode-cn.com/problems/spiral-matrix/
2.2 我的题解
题目描述
给定一个m
行n
列的矩阵matrix
,按照顺时针螺旋的顺序将它的所有元素用新的一个数组存放再返回出来。
样例
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
算法
(建立坐标系) O ( m n ) O(mn) O(mn)
按照上面的顺序,对数据进行模拟,设置类似于BFS的偏移量dx, dy
,总共为4个方向,每个方向遍历完就换另外一个方向,由此往复,就能将所有的元素顺时针螺旋遍历到。
时间复杂度:由于要遍历m*n
次,所以时间复杂度是 O ( m n ) O(mn) O(mn)
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> res;
int m = matrix.size();
if (!m) return res;
int n = matrix[0].size();
int dx[] = {
0, 1, 0, -1}, dy[] = {
1, 0, -1, 0};
vector<vector<bool>> st(m, vector<bool>(n)); // 初始化一个状态数组
for (int i = 0, x = 0, y = 0, d = 0; i < m * n; ++i) {
res.push_back(matrix[x][y]);
st[x][y] = true;
int a = x + dx[d], b = y + dy[d];
if (a < 0 || a >= m || b < 0 || b >= n || st[a][b]) {
d = (d + 1) % 4; // d有四个,所以每次更新就模4
a = x + dx[d], b = y + dy[d];
}
x = a, y = b;
}
return res;
}
};
leetcode 59 螺旋矩阵Ⅱ
3.1 题目链接
传送门:https://leetcode-cn.com/problems/spiral-matrix-ii/submissions/
3.2 我的题解
题目描述
给定一个正整数n
,让你帮忙生成一个1
到n^2
的螺旋矩阵。
样例
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
算法
(建立坐标系) O ( n 2 ) O(n^2) O(n2)
和上一题方法一摸一样,使用偏移量,当访问不下去了,就换另一条路走;
时间复杂度:由于矩阵大小是n*n
,所以时间复杂度是 O ( n 2 ) O(n^2) O(n2)
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> Matrix(n, vector<int>(n));
if (!n) return Matrix;
int dx[] = {
0, 1, 0, -1}, dy[] = {
1, 0, -1, 0};
vector<vector<bool>> st(n, vector<bool>(n));
for (int i = 1, x = 0, y = 0, d = 0; i <= n * n; ++i) {
Matrix[x][y] = i;
int a = x + dx[d], b = y + dy[d];
if (a < 0 || a >= n || b < 0 || b >= n || Matrix[a][b]) {
d = (d + 1) % 4;
a = x + dx[d], b = y + dy[d];
}
x = a, y = b;
}
return Matrix;
}
};
leetcode 66 加一
4.1 题目链接
传送门:https://leetcode-cn.com/problems/plus-one/
4.2 我的题解
题目描述
给定一个数组,数组中从头到尾的数字串起来表示一个整数。要在该数的基础上加一。然后再将加一过后的整数挨个存储在数组中。除了0之外,数组中的元素都不会以0开头。
样例
输入:digits = [1,2,3]
输出:[1,2,4]
解释:输入数组表示数字 123。
算法
(模拟) O ( n ) O(n) O(n)
取一个数出来,进行模拟加一后的结果,发现可能会发生进位,这就类似于高精度加法,也就是应该将原数组中的元素reverse
一遍,让进位存在数组的尾部,最后再reverse
回来。
时间复杂度:由于需要遍历数组中的每一位一次,所以时间复杂度是 O ( n ) O(n) O(n)。
class Solution {
public:
vector<int> plusOne(vector<int>& digits) {
reverse(digits.begin(), digits.end());
int t = 1; // 由于题目要求在该数的基础上加上一
for (int i = 0; i < digits.size(); ++i) {
t += digits[i];
digits[i] = t % 10; // 覆盖原来的元素
t /= 10;
}
if (t) digits.push_back(t);
reverse(digits.begin(), digits.end());
return digits;
}
};
剑指offer 3 数组中重复的数字
5.1 题目链接
传送门:https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/
5.2 我的题解
题目描述
给定一个长度为n
的数组,已知数组的所有数字都在0~n-1
的范围内,数组中有的数字会重复,但是不知道重复了多少个,返回任意一个重复的数字。
样例
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
算法1
(原地交换) O ( n ) O(n) O(n)
下面的算法的主要思想是把每一个元素放在对应的位置上去,即nums[i] = i
(如下图所示的效果)。
- 如果
x != i && nums[x] == x
,说明了 x x x已经出现了多次,直接返回 x x x。 - 如果
nums[x] != x
,那就需要将 x x x交换到正确的位置上去,即swap(nums[x], nums[i])
,交换完之后如果nums[i] != i
,则重复此操作。由于每次交换都会将一个数放在正确的位置上,所以swap操作最多进行 n n n次,不会发生死循环。
循环结束过后,如果没有找到重复的数,则返回-1
。
时间复杂度:每次swap
操作都会将一个数放在正确的位置,最后一次swap
会将两个数放在正确的位置,一共只有