LeetCode Hot100刷题指南(第二期)
大家好 我是寸铁
临近秋招,让我们一起刷题吧
每期5道题 持续更新中:running:
欢迎点赞 + 关注
往期回顾
操作系统期末题库 第五期
蓝桥杯上岸全指南
LeetCode Hot100刷题指南(第一期)
数据库SQL语句(期末冲刺不挂科)
暑假完善蓝桥杯和Leetcode系列,欢迎各位同学前来交流
第二期
53. 最大子数组和
分析
要找出一个最大和的连续子数组
不妨枚举以每个数结尾的最大连续子数组
思想
动态规划:
有两种选择:
一种是单独一个数
一种是和前面的数字合并成一个数组
我们可以对这两种情况取一个最大值
再更新当前的最大和
时间复杂度
枚举n个数字,一重for循环。
时间复杂度为O(n)
Accode
class Solution {
public int maxSubArray(int[] nums) {
int pre = 0 , ans = nums[0];
for(int x : nums){
pre = Math.max(pre + x , x);
ans = Math.max(pre , ans);
}
return ans;
}
}
56. 合并区间
分析
先对数组区间进行排序,先对左端点排序,再对右端点排序。
合并分为3种情况:
1.上一个区间的左端点和下一个区间的左端点相等
则区间的左端点更新为上一区间的左端点。
区间的右端点更新为下一区间的右端点。
2.下一个区间的左端点在上一个区间的左端点和下一个区间的右端点之间
则更新区间的左端点为上一个区间的左端点。
右端点更新为下一个区间的右端点
3.没有重合,则不用合并。
可以发现,除了第3种情况,剩下两种情况的处理结果一致。
我们可以单独为第3种情况进行特判。
再对1、2情况进行合并即可
1、2两种情况的左端点其实不用更新,只需要更新右端点即可
更新方式为取当前两个区间的右端点的最大值
时间复杂度
一重for循环即可实现
总计:O(n)
ACcode
class Solution {
public int[][] merge(int[][] a) {
List<int []> res = new ArrayList<>();
Arrays.sort(a , (x , y)-> x[0] - y[0]);
int l = a[0][0] , r = a[0][1];
for(int i = 1; i < a.length; i++){
//没有重合的端点
if(a[i][0] > r){
res.add(new int []{l , r});
l = a[i][0];
r = a[i][1];
}
//有重合的端点,更新右端点即可。
else{
r = Math.max(r , a[i][1]);
}
}
res.add(new int []{l , r});
return res.toArray(new int[0][]);
}
}
189. 轮转数组
解题思路
翻转数组,对数组中的每个数字向右移动 k
步后翻转。
数组长度为 n
,对于数组的数组下标 i
。
移动k步进行数组元素翻转, 即 i + k
(i+k) % n
获得在数组中翻转的相对位置
如果说某个位置i
出现(i + k ) % n == 0
则说明i后面的数字翻转时,翻转的位置从下标0
开始。
注意
arr[]
数组为空数组
移动后的位置对应的元素为nums[i]
需要再把nums[i]
的值复制到移动后的位置上的arr[]
中
代码
class Solution {
public void rotate(int[] nums, int k) {
int n = nums.length;
int []arr = new int[n];
for(int i = 0; i < n; i++){
arr[(i + k) % n] = nums[i];
}
System.arraycopy(arr, 0, nums , 0 , n);
}
}
238. 除自身以外数组的乘积
解题思路
假设当前下标为i
除自身外的乘积可以分为两部分乘积相乘
一部分是左半部分即i - 1 即L[i]
一部分是右半部分即i + 1 即R[i]
再将这两半部分乘积即可:L[i] * R[i]
注意
L[i]:第i个数的左边的乘积
R[i]: 第i个数的右边的乘积
初始化:
L[0] = 1
R[n-1]=1
用于后面数字的累乘
由于L[0] = 1
所以L[]
循环的终止条件
i = 1; i < n
由于R[n-1] = 1
所以R[]
循环的终止条件
i = n-2; i >= 0
Accode
class Solution {
public int[] productExceptSelf(int[] nums) {
int n = nums.length;
int L[] = new int [n];
int R[] = new int [n];
int ans[] = new int [n];
L[0] = 1;
for(int i = 1; i < n ; i++){
L[i] = L[i - 1] * nums[i - 1];
}
R[n - 1] = 1;
for(int i = n - 2; i >= 0; i--){
R[i] = R[i + 1] * nums[i + 1];
}
for(int i = 0; i < n; i++){
ans[i] = L[i] * R[i];
}
return ans;
}
}
73. 矩阵置零
解题思路
先看数据范围:1 <= m, n <= 200
两重for循环枚举最多为O(m*n) = O(40000)
可以过
我们只需要在矩阵中遇到数字为0
的位置
记录当前数字所在的行数和列数
再去更新该行的每一个列数字均为0
更新该列的每一行数字均为0
时间复杂度
两重for循环枚举最多为 O(mn)
Accode
class Solution {
public void setZeroes(int[][]a) {
int n = a.length;
int m = a[0].length;
boolean [] row = new boolean[n];//行
boolean [] col = new boolean[m];//列
for(int i=0; i < n; i++){
for(int j = 0; j < m; j++){
if(a[i][j] == 0){
row[i] = col[j] = true;//记录 i行 j列
}
}
}
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
if(row [i] || col[j]){
a[i][j] = 0;
}
}
}
}
}
☀️☀️☀️☀️☀️☀️
后续有补充,持续更新中🌋
喜欢的伙伴点点赞,关个注💗