【HOT100第四天】除自身以外数组的乘积,矩阵置零,螺旋矩阵,旋转图像

devtools/2024/11/18 7:24:43/

今天感觉是边界值练习专场。。。整体难度不大但是细节还是需要多动手写一写。

238. 除自身以外的数组的乘积

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

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

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

 没看提示前隐隐约约感觉应该用前缀法,但是没想清楚到底要如何下手。原来这道题是要把前缀和后缀结合着一起用!

稍微回顾一下前缀法吧!上一次使用前缀法是在 560.和为K的子数组 这里用的,主要思路就是借助a_{n}=S_{n}-S_{n-1}来推导出一个子串中元素的和如何用前缀和来表示和计算。

这里思路也差不多,不过既然要算的是数组的乘积,就暂且叫它前缀积数组 pre(n,1) 吧!【后面n和1的意思就是长度为n,每一项默认值为1】然后后缀积数组 suf(n,1) 。

思考一下 ans 数组的每一项是怎么计算出来的,以{1,2,3,4}为例,ans[0]=2x3x4,ans[1]=1x3x4。。。。如果把乘进去的数字分类,不就可以分成 i 之前的数字和 i 之后的数字吗?这不就是(前缀积x后缀积)吗。这样代码就可以写出来了👇【三个for循环可以写成两个,后两个可以合并在一起写】

class Solution {
public:vector<int> productExceptSelf(vector<int>& nums) {int n=nums.size();vector<int> ans(n,1),pre(n,1),suf(n,1);for(int i=1;i<n;i++){pre[i]=pre[i-1]*nums[i-1];}for(int i=n-2;i>=0;i--){suf[i]=suf[i+1]*nums[i+1];}for(int i=0;i<n;i++){ans[i]=pre[i]*suf[i];}return ans;}
};

因为考虑到只要数组中有一个数字是0,那么ans中除了0这个位置的乘积以外,其他地方一定为零,那可以尝试剪枝。

但写完比较了一下执行用时并没有显著提升,还不如从 把第二个和第三个for循环写在一起 的方法出发来改进。因为思路还是一样的所以就不写了。

class Solution {
public:vector<int> productExceptSelf(vector<int>& nums) {int n=nums.size(),flag=-1;vector<int> ans(n),pre(n,1),suf(n,1);for(int i=1;i<n;i++){pre[i]=pre[i-1]*nums[i-1];if(nums[i]==0){flag=i;break;}}for(int i=n-2;i>=0;i--){suf[i]=suf[i+1]*nums[i+1];if(flag>0&&i==flag) break;}if(flag>0){ans[flag]=pre[flag]*suf[flag];return ans;}for(int i=0;i<n;i++){ans[i]=pre[i]*suf[i];}return ans;}
};

一点点小感想:以后做算法题,如果看到 “数组” “元素之间的计算” “无序” 这几个属性,多半就可以考虑一下是不是应该用前缀法做了。

 73. 矩阵置零

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

进阶:

  • 一个直观的解决方案是使用  O(mn) 的额外空间,但这并不是一个好的解决方案。
  • 一个简单的改进方案是使用 O(m + n) 的额外空间,但这仍然不是最好的解决方案。
  • 你能想出一个仅使用常量空间的解决方案吗?

定睛一看专业对口,之前做数独游戏的时候,高亮选中数字的行和列时也用过相似的算法,只要保存好要处理的行和列,最后修改一下就行了。

class Solution {
public:void setZeroes(vector<vector<int>>& matrix) {int rows = matrix.size();int cols = matrix[0].size();vector<bool> zeroRows(rows, false);vector<bool> zeroCols(cols, false);for (int i = 0; i < rows; ++i) {for (int j = 0; j < cols; ++j) {if (matrix[i][j] == 0) {zeroRows[i] = true;zeroCols[j] = true;}}}for (int i = 0; i < rows; ++i) {if (zeroRows[i]) {for (int j = 0; j < cols; ++j) {matrix[i][j] = 0;}}}for (int j = 0; j < cols; ++j) {if (zeroCols[j]) {for (int i = 0; i < rows; ++i) {matrix[i][j] = 0;}}}}
};

结果一看进阶要求,居然可以仅用一个常量空间解决吗??

 先挖个坑改天看看。。。太困了。。。

54. 螺旋矩阵

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

 

第一眼:有点意思

第二眼:纯折磨(。。。)

主要就是找到应该如何循环,然后划分成四个方向(也就是四个for循环),还有四个边界(top、bottom、left、right),上下左右,每次遍历完一个方向,就通过减小边界值来缩小边界。

注意while循环的边界值,如果只有一行数了,将会出现top=bottom和left=right的情况,所以要带上等于。

【如果一直内存地址溢出,就多看看边界值是不是设错了,m和n是不是设反了】

class Solution {
public:vector<int> spiralOrder(vector<vector<int>>& matrix) {int m = matrix.size(), n = matrix[0].size();if (m == 0 || n == 0)return {};int top = 0, bottom = m - 1, left = 0, right = n - 1;vector<int> ans;while (top <= bottom && left <= right) {for (int i = left; i <= right; i++) ans.emplace_back(matrix[top][i]);top++;if (top > bottom) break;for (int i = top; i <= bottom; i++) ans.emplace_back(matrix[i][right]);right--;if (left > right) break;for (int i = right; i >= left; i--) ans.emplace_back(matrix[bottom][i]);bottom--;if (top > bottom) break;for (int i = bottom; i >= top; i--) ans.emplace_back(matrix[i][left]);left++;if (left > right) break;}return ans;}
};

48.旋转图像

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

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

想学线性代数的有福了。思考一下可不可以通过简单的矩阵变换,让当前矩阵变成旋转90度的样子?

有的,先延水平轴翻转一下,再延对角线翻转,像这样:

\begin{bmatrix} 1 & 2 & 3\\ 4 & 5 & 6\\ 7& 8& 9 \end{bmatrix}  水平向下翻转👉\begin{bmatrix} 7 & 8 &9 \\ 4& 5& 6\\ 1 & 2 & 3 \end{bmatrix}  最后延对角翻转👉 \begin{bmatrix} 7 & 4 &1 \\ 8& 5& 2\\ 9 & 6 & 3 \end{bmatrix}

注意,代码中想要实现翻转,只需要遍历一半的数组,不是全部(不然就翻转回来了)。

class Solution {
public:void rotate(vector<vector<int>>& matrix) {int n=matrix.size();for(int i=0;i<n/2;i++){for(int j=0;j<n;j++){swap(matrix[i][j],matrix[n-i-1][j]);}}for(int i=0;i<n;i++){for(int j=0;j<i;j++){swap(matrix[i][j],matrix[j][i]);}}}
};

 


http://www.ppmy.cn/devtools/134898.html

相关文章

【C语言】连接陷阱探秘(2):命令冲突与static修饰符

目录 一、命令冲突 1.1. 常见情况及原因 1.1.1. 符号重定义冲突 1.1.2. 不同编译单元中静态函数调用冲突 1.2. 解决办法 1.3. 示例 二、static 修饰符的陷阱与缺陷 2.1. 变量方面的陷阱 2.1.1. 静态局部变量的初始化顺序问题 2.1.2. 静态全局变量的作用域误解 2.2. …

【AI图像生成网站Golang】项目架构

AI图像生成网站 目录 一、项目介绍 二、雪花算法 三、JWT认证与令牌桶算法 四、项目架构 五、图床上传与图像生成API搭建 六、项目测试与调试(等待更新) 四、项目架构 本项目的后端基于Golang和Gin框架开发&#xff0c;主要包括的模块有&#xff1a; backend/ ├── …

第8章:TDengine 开发、测试、生产三大环境中数据库创建指南

TDengine 开发、测试、生产三大环境中数据库创建指南 TDengine3.0社区版在开发、测试、以及生产三大环境中数据库创建SQL语句以及相应参数的说明文档。 一、概述 TDengine3.0社区版是一款开源、高性能、云原生的时序数据库,支持SQL语法,并针对时序数据进行了优化。在开发、…

QT适配最新版Android SDK

从AndroidStudio的SDK管理下载最新版SDK 从https://www.androiddevtools.cn/下载国内安卓SKDTools 这里下载SKDTools后不需要使用SDK Manager.exe下载SDK&#xff08;SDK Manager.exe下载的SDK都是旧版&#xff0c;没法支持新版本&#xff09;&#xff0c;直接使用从AndroidS…

web-02

回顾 full stack web前端 结构(html) 样式(css) 动作/交互(js) html html常用标签 扩展标签 列表 ul/ol u–un – 无序的 o-order --有顺序的 <ol> 你最喜欢的游戏是什么&#xff1f;<li>bar sleep</li><li>who knows</li> </ol>布…

Apache Doris:深度优化与最佳实践

引言 在前两篇文章中&#xff0c;我们已经介绍了 Apache Doris 的基本概念、安装配置、基础操作以及一些高级特性。本文将进一步深入探讨 Doris 的性能优化技巧、高级查询优化、数据建模最佳实践以及常见问题的解决方法。通过本文&#xff0c;读者将能够更好地理解和应用 Dori…

大语言模型LLM综述

一、LM主要发展阶段 1.1、统计语言模型SLM 基于统计学习方法&#xff0c;基本思想是基于马尔可夫假设HMM建立词概率预测模型。如n-gram语言模型 1.2、神经语言模型NLM 基于神经网络来做词的分布式表示。如word2vec模型 1.3、 预训练语言模型PLM 预训练一个网络模型来做词表…

【异常解决】Linux shell报错:-bash: [: ==: 期待一元表达式 解决方法

博主介绍&#xff1a;✌全网粉丝21W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…