当前位置: 首页 > news >正文

【LeetCode Solutions】LeetCode 热题 100 题解(16 ~ 20)

CONTENTS

  • 普通数组 - LeetCode 238. 除自身以外数组的乘积(中等)
  • 普通数组 - LeetCode 41. 缺失的第一个正数(困难)
  • 矩阵 - LeetCode 73. 矩阵置零(中等)
  • 矩阵 - LeetCode 54. 螺旋矩阵(中等)
  • 矩阵 - LeetCode 48. 旋转图像(中等)

普通数组 - LeetCode 238. 除自身以外数组的乘积(中等)

【题目描述】

给你一个整数数组 nums,返回数组 answer,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。

题目数据保证数组 nums 之中任意元素的全部前缀元素和后缀的乘积都在 32 位整数范围内。

不要使用除法,且在 O(n)O(n)O(n) 时间复杂度内完成此题。

【示例 1】

输入: nums = [1,2,3,4]
输出: [24,12,8,6]

【示例 2】

输入: nums = [-1,1,0,-3,3]
输出: [0,0,9,0,0]

【提示】

2<=nums.length<=1052 <= nums.length <= 10^52<=nums.length<=105
−30<=nums[i]<=30-30 <= nums[i] <= 3030<=nums[i]<=30
输入保证数组 answer[i] 在 32 位整数范围内

进阶:你可以在 O(1)O(1)O(1) 的额外空间复杂度内完成这个题目吗?(出于对空间复杂度分析的目的,输出数组不被视为额外空间)


【分析】

本题是前缀和的思想,不考虑空间要求的情况下我们可以预处理出两个数组 p[i]p[i]p[i]s[i]s[i]s[i] 分别表示 iii 之前所有数的乘积(nums[0]∗nums[1]∗⋯∗nums[i−1]nums[0] * nums[1] * \dots * nums[i - 1]nums[0]nums[1]nums[i1])以及 iii 之后所有数的乘积(nums[i+1]∗nums[i+2]∗⋯∗nums[n−1]nums[i + 1] * nums[i + 2] * \dots * nums[n - 1]nums[i+1]nums[i+2]nums[n1])。

题目要求我们只能开一个额外的答案数组,那么我们可以将数组 sss 省去,先在输出数组中预处理出前缀乘积 ppp,然后我们再倒序遍历数组,遍历的过程中用一个变量记录当前的后缀乘积即可。


【代码】

class Solution {
public:vector<int> productExceptSelf(vector<int>& nums) {int n = nums.size();vector<int> res(n);res[0] = 1;  // 边界初始化for (int i = 1; i < n; i++)res[i] = res[i - 1] * nums[i - 1];  // res[i] 表示 [0, i - 1] 区间中所有元素的乘积for (int i = n - 1, mul = 1; ~i; i--)res[i] *= mul, mul *= nums[i];  // mul 表示 [i + 1, n - 1] 区间中所有元素的乘积return res;}
};

普通数组 - LeetCode 41. 缺失的第一个正数(困难)

【题目描述】

给你一个未排序的整数数组 nums,请你找出其中没有出现的最小的正整数

请你实现时间复杂度为 O(n)O(n)O(n) 并且只使用常数级别额外空间的解决方案。

【示例 1】

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

【示例 2】

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

【示例 3】

输入:nums = [7,8,9,11,12]
输出:1

【提示】

1≤nums.length≤5∗1051\le nums.length\le 5 * 10^51nums.length5105
−231≤nums[i]≤231−1-2^{31}\le nums[i]\le 2^{31} - 1231nums[i]2311


【分析】

注意本题的时空复杂度,不能用排序以及哈希表之类的做法。

我们可以用置换的方法求解,我们记 nnnnumsnumsnums 的长度,因此答案一定在 1∼n+11\sim n+11n+1 之间(因为最完美的情况是 numnumnum 中有 1∼n1\sim n1n)。

我们利用两两交换的方法将 numnumnum 中在 1∼n1\sim n1n 范围内的数放置到其对应的位置上,也就是 nums[i] = i + 1。但其中有若干个位置上的数是错误的,每一个错误的位置就代表了一个缺失的正数。以 [3, 4, -1, 1] 为例,置换后的数组应当为 [1, -1, 3, 4],我们就可以知道缺失的数为 222

注意在交换的过程中应判断两数是否相等防止死循环。


【代码】

class Solution {
public:int firstMissingPositive(vector<int>& nums) {int n = nums.size();for (int i = 0; i < n; i++)// 将当前数置换到其对应的位置 num[i] - 1while (nums[i] > 0 && nums[i] <= n && nums[i] != nums[nums[i] - 1])swap(nums[i], nums[nums[i] - 1]);for (int i = 0; i < n; i++)if (nums[i] != i + 1) return i + 1;  // 该位置上没有对应的正整数说明缺失了return n + 1;  // 1 ~ n 全部没有缺失}
};

矩阵 - LeetCode 73. 矩阵置零(中等)

【题目描述】

给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。

【示例 1】

在这里插入图片描述

输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[1,0,1],[0,0,0],[1,0,1]]

【示例 2】

在这里插入图片描述

输入:matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
输出:[[0,0,0,0],[0,4,5,0],[0,3,1,0]]

【提示】

m==matrix.lengthm == matrix.lengthm==matrix.length
n==matrix[0].lengthn == matrix[0].lengthn==matrix[0].length
1≤m,n≤2001\le m, n\le2001m,n200
−231≤matrix[i][j]≤231−1-2^{31}\le matrix[i][j]\le 2^{31}-1231matrix[i][j]2311


【分析】

我们需要用原矩阵的第一行来记录每一列是否有 0,用第一列来记录每一行是否有 0。但是第一行与第一列是否有 0 的信息无法保存,因此还需要使用两个额外的变量来记录第一行与第一列是否有 0。


【代码】

class Solution {
public:void setZeroes(vector<vector<int>>& g) {bool r0 = false, c0 = false;  // 第一行或者第一列是否有 0for (int i = 0; i < g[0].size(); i++)  // 判断第一行是否有 0if (!g[0][i]) { r0 = true; break; }for (int i = 0; i < g.size(); i++)  // 判断第一列是否有 0if (!g[i][0]) { c0 = true; break; }for (int i = 1; i < g.size(); i++)  // 判断其余行是否有 0for (int j = 1; j < g[0].size(); j++)if (!g[i][j]) { g[i][0] = 0; break; }for (int i = 1; i < g[0].size(); i++)  // 判断其余列是否有 0for (int j = 1; j < g.size(); j++)if (!g[j][i]) { g[0][i] = 0; break; }for (int i = 1; i < g[0].size(); i++)  // 遍历第一行,将为 0 的元素所在的列置零if (!g[0][i])for (int j = 1; j < g.size(); j++)g[j][i] = 0;for (int i = 1; i < g.size(); i++)  // 遍历第一列,将为 0 的元素所在的行置零if (!g[i][0])for (int j = 1; j < g[0].size(); j++)g[i][j] = 0;if (r0) for (int i = 0; i < g[0].size(); i++) g[0][i] = 0;  // 第一行置零if (c0) for (int i = 0; i < g.size(); i++) g[i][0] = 0;  // 第一列置零}
};

矩阵 - LeetCode 54. 螺旋矩阵(中等)

【题目描述】

给你一个 mn 列的矩阵 matrix,请按照顺时针螺旋顺序,返回矩阵中的所有元素。

【示例 1】

在这里插入图片描述

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]

【示例 2】

在这里插入图片描述

输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]

【提示】

m==matrix.lengthm == matrix.lengthm==matrix.length
n==matrix[i].lengthn == matrix[i].lengthn==matrix[i].length
1≤m,n≤101\le m, n\le 101m,n10
−100≤matrix[i][j]≤100-100\le matrix[i][j]\le 100100matrix[i][j]100


【分析】

分别设置向右、向下、向左、向上四个方向向量,然后模拟一遍即可,走出界或是已经遍历过了改变一下方向即可。


【代码】

class Solution {
public:vector<int> spiralOrder(vector<vector<int>>& matrix) {int n = matrix.size(), m = matrix[0].size();int dx[] = { 0, 1, 0, -1 }, dy[] = { 1, 0, -1, 0 };  // 分别表示右、下、左、上的方向向量vector<int> res;for (int i = 0, x = 0, y = 0, d = 0; i < n * m; i++) {  // 总共遍历 n * m 个点res.push_back(matrix[x][y]);matrix[x][y] = INT_MIN;  // 遍历过的数修改为 INT_MINint nx = x + dx[d], ny = y + dy[d];if (nx < 0 || nx >= n || ny < 0 || ny >= m || matrix[nx][ny] == INT_MIN) d = (d + 1) % 4;x += dx[d], y += dy[d];}return res;}
};

矩阵 - LeetCode 48. 旋转图像(中等)

【题目描述】

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。

【示例 1】

在这里插入图片描述

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]

【示例 2】

在这里插入图片描述

输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]

【提示】

n==matrix.length==matrix[i].lengthn == matrix.length == matrix[i].lengthn==matrix.length==matrix[i].length
1≤n≤201\le n\le 201n20
−1000≤matrix[i][j]≤1000-1000\le matrix[i][j]\le 10001000matrix[i][j]1000


【分析】

我们先给出一个变换过程的例子:

1 2 3      1 4 7      7 4 1
4 5 6  =>  2 5 8  =>  8 5 2
7 8 9      3 6 9      9 6 3

该过程很简单,但是没有接触过类似题目的话确实很难想出来,首先沿着主对角线进行翻转,然后沿着列的中轴进行翻转即可。


【代码】

class Solution {
public:void rotate(vector<vector<int>>& matrix) {int n = matrix.size();// 沿对角线翻转for (int i = 0; i < n; i++)for (int j = i + 1; j < n; j++)swap(matrix[i][j], matrix[j][i]);// 沿列中轴线翻转for (int i = 0; i < n; i++)for (int j = 0; j < n >> 1; j++)swap(matrix[i][j], matrix[i][n - 1 - j]);}
};
http://www.lryc.cn/news/599500.html

相关文章:

  • 系统编程——文件IO
  • SpringBoot整合Fastexcel/EasyExcel导出Excel导出多个图片
  • 面向对象编程实战:Python打造你的数码宠物世界
  • Java NIO FileChannel在大文件传输中的性能优化实践指南
  • 盟接之桥说制造:构建以预防为核心的供应链客诉管理体系
  • GitHub git push 推送大文件
  • 【第四章:大模型(LLM)】01.Embedding is all you need-(6)从 Word2Vec 到推荐/广告系统,再到大语言模型(LLM)
  • Three.js 控制器和交互设计:OrbitControls + Raycaster 实战
  • ✨ 使用 Flask 实现头像文件上传与加载功能
  • Kafka——多线程开发消费者实例
  • MCP工具开发实战:打造智能体的“超能力“
  • 半相合 - 脐血联合移植
  • C++ 常用的数据结构(适配器容量:栈、队列、优先队列)
  • 海云安斩获“智能金融创新应用“标杆案例 彰显AI安全左移技术创新实力
  • 智能网关芯片:物联网连接的核心引擎
  • VR 污水处理技术赋能广州猎德污水处理厂,处理效率显著提升
  • FastDFS如何提供HTTP访问电子影像文件
  • 网络协议,DHCP 协议等。
  • 每日面试题14:CMS与G1垃圾回收器的区别
  • http-proxy-middleware MaxListenersExceededWarning
  • Java 大视界 -- 基于 Java 的大数据分布式存储在工业互联网数据管理与边缘计算协同中的创新实践(364)
  • 零碳园区如何破局?安科瑞EMS3.0以智慧能源管理重构低碳未来
  • 借助Aspose.HTML控件,在 Python 中将 SVG 转换为 PDF
  • Kimi K2 大语言模型技术特性与应用实践分析
  • 酷暑来袭,科技如何让城市清凉又洁净?
  • 冠捷科技 | 内生外化,精准触达,实现数字化转型精准赋能
  • Pytorch混合精度训练最佳实践
  • 人工智能冗余:大语言模型为何有时表现不佳(以及我们能做些什么)
  • 广东省省考备考——常识:科技常识(持续更新)
  • 【指南版】网络与信息安全岗位系列(一):网络安全工程师