【面试HOT100】子串普通数组矩阵

系列综述:
💞目的:本系列是个人整理为了秋招面试的,整理期间苛求每个知识点,平衡理解简易度与深入程度。
🥰来源:材料主要源于LeetCodeHot100进行的,每个知识点的修正和深入主要参考各平台大佬的文章,其中也可能含有少量的个人实验自证。
🤭结语:如果有帮到你的地方,就点个赞关注一下呗,谢谢🎈🎄🌷!!!
🌈【C++】秋招&实习面经汇总篇


文章目录

      • 基本算法
      • 子串篇
        • 560. 和为 K 的子数组
        • 239. 滑动窗口最大值(单调队列)
        • 76. 最小覆盖子串
      • 普通数组篇
        • 53. 最大子数组和
        • 56. 合并区间
        • 189. 轮转数组
        • 238. 除自身以外数组的乘积
        • 41. 缺失的第一个正数
      • 矩阵篇
        • 73. 矩阵置零
        • 54. 螺旋矩阵
        • 48.旋转图像
        • 240. 搜索二维矩阵 II
    • 参考博客


😊点此到文末惊喜↩︎

基本算法

  1. 排序
  2. set去重
  3. 哈希:数组全部扔入unordered_map可通过O(1)时间进行查找

子串篇

560. 和为 K 的子数组
  1. 问题
    • 给你一个整数数组 nums 和一个整数 k
    • 请你统计并返回 该数组中和为 k 的连续子数组的个数 。
  2. 思路
    • 滑动窗口:无法通过sum>k判断负数问题
    • 暴力方法
    • 前缀和(公式变换思想)
      • [left,right]区间的和为k 等价于 前right项的和 - 前left-1项的和 = k
      • 单下标转化:前left-1项的和(历史值) = 前right项的和(先锋值) - k。先锋值需要一直记录求解,而历史值可以将先锋值记录在map中,方便以O(1)时间查找
int subarraySum(vector<int>& nums, int k) {int sum = 0, res = 0;// 第一次前缀和恰好等于k时,则sum为0,值为1unordered_map<int, int> umap{{0, 1}};for (int& c : nums) {sum += c;		// 记录和if (umap.count(sum - k) > 0)res += umap[sum - k];++umap[sum];	// 如果有负数,不同位置可能有相同的前缀和}	return res;
}
  1. 总结
    • unordered_map比map更加节省空间
    • 使用if (umap.count(target_key) > 0),判断目标元素是否存在
239. 滑动窗口最大值(单调队列)
  1. 问题
    • 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。
    • 你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回每次滑动窗口中的最大值 。
  2. 思路
    • 定义大根堆处理最值,每次滑动将新元素加入堆中并记录滑出元素,如果弹出最大元素不在滑出元素中即为结果,若是滑出元素则继续弹出堆顶元素。
    • 单调队列:维护一个单调队列(从大到小)
      • push时:从与队尾元素比较,如果小于cur则从队尾弹出,直到最后压入元素
      • pop时:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {// 单调队列deque<int> que;// 弹出元素:若为left元素则弹出auto pop = [&que](int value){   if (!que.empty() && value == que.front()) que.pop_front();};// 压入元素:从尾部弹出所有比压入值小的,保证队首元素是最大的auto push =[&que](int value){   while (!que.empty() && value > que.back()) que.pop_back();que.push_back(value);};vector<int> result;for (int i = 0; i < k; i++) { // 先将前k的元素放进队列push(nums[i]);}result.push_back(que.front()); // result 记录前k的元素的最大值for (int i = k; i < nums.size(); i++) {pop(nums[i - k]); // 滑动窗口移除最前面元素push(nums[i]); // 滑动窗口前加入最后面的元素result.push_back(que.front()); // 记录对应的最大值}return result;
}
76. 最小覆盖子串
  1. 问题
    • 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。
    • 如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
    • 输入:s = “ADOBECODEBANC”, t = “ABC”
    • 输出:“BANC”
  2. 思路
    • 代码手法:先记录值,然后进行增量条件,最后再对值进行复杂的条件判断
// 返回字符串 s 中包含字符串 t 的全部字符的最小窗口
string SlideWindow(string s, string t) {// need记录子串情况,window记录合适窗口unordered_map<char, int> need, window;for (char c : t) need[c]++;int left = 0, right = 0;// 记录最小覆盖子串的起始索引及长度int start = 0, len = INT_MAX;int valid = 0;while (right < s.size()) {// 记录操作值,然后再进行复杂条件判断char c = s[right];	// c 是将移入窗口的字符right++;			// 右移窗口// 进行窗口内数据的一系列更新if (need.count(c)) { // 判断need中是否存在cwindow[c]++;if (window[c] == need[c])valid++;}while (valid == need.size()) {	// TODO:收缩条件// TODO:更新结果记录if (right - left < len) {	start = left;// 更新起始值len = right - left;// 最小长度}// 收缩窗口char d = s[left];left++;// TODO:收缩处理if (need.count(d)) {if (window[d] == need[d])valid--;window[d]--;}                    }}// 返回最小覆盖子串return len == INT_MAX ?"" : s.substr(start, len);
}

普通数组篇

53. 最大子数组和
  1. 问题
    • 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组
    • 子数组最少包含一个元素,返回其最大和。(子数组 是数组中的一个连续部分)
  2. 思路
    • 贪心思路:负数一定是拉低总和。一直保存连续区间的最大值,如果连续区间值为负数,则重新开始计算连续区间值
    • 动态规划:对于过去状态是否选择的一个标准
// 贪心
int maxSubArray(vector<int>& nums) {int result = INT32_MIN;int count = 0;for (int i = 0; i < nums.size(); i++) {count += nums[i];if (count > result) { // 取区间累计的最大值(相当于不断确定最大子序终止位置)result = count;}if (count <= 0) count = 0; // 相当于重置最大子序起始位置,因为遇到负数一定是拉低总和}return result;
}// 动态规划
int maxSubArray(vector<int>& nums) {int len = nums.size();// dp[i] 表示:以 nums[i] 结尾的连续子数组的最大和vector<int> dp(len);dp[0] = nums[0];for (int i = 1; i < len; i++) {// 状态转移:是否选择过去状态dp[i-1] + 当前nums[i]if (dp[i - 1] > 0) {dp[i] = dp[i - 1] + nums[i];} else {dp[i] = nums[i];}}// 也可以在上面遍历的同时求出 res 的最大值,这里我们为了语义清晰分开写,大家可以自行选择int res = dp[0];for (int i = 1; i < len; i++) {res = max(res, dp[i]);}return res;}
56. 合并区间
  1. 问题
    • 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。
    • 请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间
  2. 思路
    • 双指针:数组的原地条件删除
vector<vector<int>> merge(vector<vector<int>>& intervals) {if (!intervals.size()) return {};sort(intervals.begin(), intervals.end(), less<vector<int>>());int slow = 0;int fast = 1;while (fast < intervals.size()) {if (intervals[slow][1] >= intervals[fast][0]) {intervals[slow][1] = max(intervals[fast][1], intervals[slow][1]);} else  {slow++;intervals[slow] = intervals[fast];}fast++;}intervals.resize(slow+1);return intervals;
}
189. 轮转数组
  1. 问题
    • 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
  2. 思路
    • 辅助存储空间,直接分段存储
    • 两次反转:整体反转,然后部分反转
    • 每次跳k个,进行覆盖,但是需要判断结束条件。
void reverse(vector<int>& nums, int start, int end) {while (start < end) {swap(nums[start], nums[end]);start += 1;end -= 1;}
}
void rotate(vector<int>& nums, int k) {k %= nums.size();reverse(nums, 0, nums.size() - 1);reverse(nums, 0, k - 1);reverse(nums, k, nums.size() - 1);
}
238. 除自身以外数组的乘积
  1. 问题
    • 给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。
    • 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。
  2. 思路
    • 分解的思想:将 n 2 n^2 n2 转化为 n + n n+n n+n 时间复杂度,res[i] = MUL(0, i-1) * MUL(i+1, end)(写公式,分析公式)
vector<int> productExceptSelf(vector<int>& nums) {const int n = nums.size();vector<int> res(n, 0);// res中每个位置左边的乘积int k = 1;for (int i = 0; i < n; i ++) {res[i] = k;k *= nums[i];}// res中每个位置乘以右边的乘积k = 1;for (int i = n - 1; i >= 0; i --) {res[i] *= k;k *= nums[i];}return res;
}
41. 缺失的第一个正数
  1. 问题
    • 给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
  2. 思路
    • 数组+交换:可以降低时间复杂度和空间复杂度
    • 原地哈希
      • 将数组视为哈希表, 1放在下标为0位置上,2放在下标为1位置上。最后,即 n u m s [ i ] = i + 1 nums[i]=i+1 nums[i]=i+1
// 原地交换
int firstMissingPositive(vector<int>& nums) {int n = nums.size();for(int i = 0; i < n; i++){// while继续确定交换回来数的位置while(nums[i] >= 1 && nums[i] <= n // 规定遍历范围&& nums[i] != nums[nums[i] - 1]){  // 避免原地交换,因为已经成功了swap(nums[i], nums[nums[i] - 1]);	// 将值nums[i]交换到目标位置num[nums[i] - 1]}}for(int i = 0; i < n; i++){if(nums[i] != i + 1)return i + 1;}return n + 1;
}// 哈希法(空间O(n))
int firstMissingPositive(vector<int>& nums) {int n=nums.size();unordered_map<int,bool> hashmap;for(int& num:nums){hashmap[num]=true;}for(int i=1;i<=n;i++){if(hashmap[i]==false) return i;}return n+1;
}

矩阵篇

解决的问题:
给定一个线性表(字符串、数组等),一次遍历求满足指定条件的连续子部分

73. 矩阵置零
  1. 问题
    • 给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。
  2. 思路
    • 有重复则去重:通过unordered_set记录,并去除行和列中的重复
    • 整体标记法(一个标记可以表示一个整体的属性):遍历对角线上每个个元素对应的行和列,若存在0则将对象线元素标记为0,最后再将标记为0的对象线元素对应的行列置为0
typedef struct {
int x;int y;
} Cord;
void setZeroes(vector<vector<int>>& matrix) {// 使用两个unordered_set分别存储需要置为0的行和列unordered_set<int> row_record;unordered_set<int> col_record;for (int i = 0; i < matrix.size(); ++i) {for (int j = 0; j < matrix[0].size(); ++j) {if (matrix[i][j] == 0) {row_record.emplace(i);col_record.emplace(j);}}}for (auto i : row_record) {for (int p = 0; p < matrix[0].size(); ++p) {matrix[i][p] = 0;}}for (auto j : col_record) {for (int p = 0; p < matrix.size(); ++p) {matrix[p][j] = 0;}}
}
54. 螺旋矩阵
  1. 问题
    • 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
  2. 思路
    • 边界变化:通过规定四个边界进行处理
vector<int> spiralOrder(vector<vector<int>>& matrix) {// 健壮性检查if (matrix.empty()) return  vector<int>();vector<int> res;int up = 0, down = matrix.size()-1;int left = 0, right = matrix[0].size()-1;while (up <= down && left <= right) {// 从左到右for (int i = left; i <= right; ++i) res.push_back(matrix[up][i]);++up;   // 缩小上边界if (up > down) break;// 从上到下for (int i = up; i <= down; ++i) res.push_back(matrix[i][right]);--right;if (left > right) break;// 从左到右for (int i = right; i >= left; i--) res.push_back(matrix[down][i]);--down;// 从左到右for (int i = down; i >= up; i--) res.push_back(matrix[i][left]);++left;}return res;
}
48.旋转图像
  1. 问题
    • 给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
    • 必须在 原地 旋转图像
  2. 思路
    • 找映射规律:原索引位置matrix[i][j] -> 旋转后索引位置matrix[i][n-1-i]
// 直接映射
void rotate(vector<vector<int>>& matrix) {int n = matrix.size();// 深拷贝 matrix -> tmpvector<vector<int>> tmp = matrix;// 根据元素旋转公式,遍历修改原矩阵 matrix 的各元素for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {matrix[j][n - 1 - i] = tmp[i][j];}}
}
// 空间优化
void rotate(vector<vector<int>>& matrix) {// 设矩阵行列数为 nint n = matrix.size();// 起始点范围为 0 <= i < n / 2 , 0 <= j < (n + 1) / 2// 其中 '/' 为整数除法for (int i = 0; i < n / 2; i++) {       // 一共转的圈数for (int j = i; j < n-i-1; j++) {   // 每一圈要处理一行对应旋转一次// 暂存 A 至 tmpint tmp = matrix[i][j];// 元素旋转操作 A <- D <- C <- B <- tmpmatrix[i][j] = matrix[n - 1 - j][i];matrix[n - 1 - j][i] = matrix[n - 1 - i][n - 1 - j];matrix[n - 1 - i][n - 1 - j] = matrix[j][n - 1 - i];matrix[j][n - 1 - i] = tmp;}}
}
  1. 总结
    • while循环一定要注意增量条件:while(条件) { ··· ++p;}
    • 看好是不是矩形,是m*n还是n*n
240. 搜索二维矩阵 II
  1. 问题
    • 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target
    • 每行的元素从左到右升序排列。
    • 每列的元素从上到下升序排列。
  2. 思路
    • 找映射规律:原索引位置matrix[i][j] -> 旋转后索引位置matrix[i][n-1-i]
bool searchMatrix(vector<vector<int>>& matrix, int target) {if(!matrix.size() && !matrix[0].size()) return false;int i = 0, j = matrix[0].size() - 1;  //矩阵右上角while(i < matrix.size() && j >= 0) {if(matrix[i][j] == target)  return true;else if( matrix[i][j] < target) i++;  //排除一行else if( matrix[i][j] > target) j--;  //排除一列}return false;
}


少年,我观你骨骼清奇,颖悟绝伦,必成人中龙凤。
不如点赞·收藏·关注一波

🚩点此跳转到首行↩︎

参考博客

  1. 前缀和问题
  2. 单调队列
  3. 快速链表quicklist
  4. 《深入理解计算机系统》
  5. 侯捷C++全系列视频
  6. 待定引用
  7. 待定引用
  8. 待定引用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/107807.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于IPSec VPN隧道技术的国密加密网关保障电力工控数据安全

IPSec VPN&#xff08;Internet Protocol Security Virtual Private Network&#xff09;隧道技术为电力工控系统提供了重要的数据安全传输手段。该技术能实现身份鉴别和数据加密传输&#xff0c;为系统的防护工作增添了有力的支持。 电力工控系统对数据传输的可靠性要求较高。…

【使用python和flask建个人博客】修复侧边栏最新文章、最多阅读等链接不能打开的问题

自从上次因版本兼容问题修改过部分代码之后,好长时间没光顾woniunote这个个人博客模块了,最近发文章的时候发现侧边栏的文章打不开,定位了bug,并进行了修复。 <div class="col-12 side"><div class="tip" align

SAP ERP系统解决光伏电池产业管理难题

无锡哲讯聚焦光伏行业的业务需求和流程&#xff0c;推出SAP光伏能源行业整体化解决方案。该系统着眼于“企业管理信息化、资源合理配置、利润扩张”三个方面&#xff0c;提供实用丰富的管理功能&#xff0c;同时具有较高的信息综合利用效率。SAP解决方案实现了光伏企业产、供、…

CEC2013(MATLAB):​白鲸优化算法(Beluga whale optimization,BWO)​求解CEC2013

一、白鲸优化算法&#xff08;Beluga whale optimization&#xff0c;BWO&#xff09; 白鲸优化算法&#xff08;Beluga whale optimization&#xff0c;BWO&#xff09;由Changting Zhong等人于2022年提出&#xff0c;该算法模拟了白鲸游泳&#xff0c;觅食和“鲸鱼坠落”行为…

linux系统中日志简介

1.linux系统中日志文件类型 主要包括三种&#xff1a; 内核及系统日志 &#xff1a;主要由 系统服务 rsyslog统一管理&#xff0c;根据服务的主配置文件 /etc/rsyslog.conf 中的设置决定 内核和系统程序消息记录的位置。用户日志 &#xff1a; 记录linux系统中用户的登录和退出…

LeetCode 面试题 10.01. 合并排序的数组

文章目录 一、题目二、C# 题解 一、题目 给定两个排序后的数组 A 和 B&#xff0c;其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法&#xff0c;将 B 合并入 A 并排序。 初始化 A 和 B 的元素数量分别为 m 和 n。 示例: 输入: A [1,2,3,0,0,0], m 3 B [2,5,6], n 3 输…

第58节——redux-toolkit中的createAsyncThunk

一、概念 createAsyncThunk 是一个由 Redux Toolkit 提供的函数&#xff0c;用于创建处理异步操作的 thunk action creator。使用 createAsyncThunk 可以简化 Redux 中处理异步操作的流程&#xff0c;使代码更加清晰、简洁。 二、参数说明 import { createAsyncThunk } from…

【算法题】2903. 找出满足差值条件的下标 I

插&#xff1a; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家一起学习鸭~~~ 题目&#xff1a; 给你一个下标从 0 开始、长度为 n …

Py之trl:trl(一款采用强化学习训练Transformer语言模型和稳定扩散模型的全栈库)的简介、安装、使用方法之详细攻略

Py之trl&#xff1a;trl(一款采用强化学习训练Transformer语言模型和稳定扩散模型的全栈库)的简介、安装、使用方法之详细攻略 目录 trl的简介 1、亮点 2、PPO是如何工作的&#xff1a;PPO对语言模型微调三步骤&#xff0c;Rollout→Evaluation→Optimization trl的安装 t…

4.3 划分子网和构造超网

思维导图&#xff1a; 4.3.1 划分子网 **4.3 划分子网和构造超网笔记&#xff1a;** --- **4.3.1 划分子网** **1. 两级IP地址到三级IP地址的转变&#xff1a;** **关键点&#xff1a;** - **问题背景&#xff1a;** 早期的ARPANET对IP地址的设计存在不足&#xff1a; 1…

LeetCode 63. 不同路径 II

63. 不同路径 II 思路&#xff1a; 动态规划 dp[i][j] &#xff1a;表示从&#xff08;0 &#xff0c;0&#xff09;出发&#xff0c;到(i, j) 有dp[i][j]条不同的路径 根据题意&#xff0c;只能向下或者向右移动一步&#xff0c;则dp[i][j] dp[i - 1][j] dp[i][j - 1] 但是…

第五十九章 学习常用技能 - 将数据从一个数据库移动到另一个数据库

文章目录 第五十九章 学习常用技能 - 将数据从一个数据库移动到另一个数据库 第五十九章 学习常用技能 - 将数据从一个数据库移动到另一个数据库 如果需要将数据从一个数据库移动到另一个数据库&#xff0c;请执行以下操作&#xff1a; 识别包含数据及其索引的Global。 如果…

Android 13.0 首次开机进入Launcher3前黑屏几秒的几种情况问题的总结

1.概述 在13.0的系统产品定制化工作中,对于系统开发确实有些难度,特别是在开机阶段遇到的问题,比如开机动画播放完毕进入锁屏界面黑屏几秒然后进入 锁屏界面,这就需要根据开机日志来分析问题所在,在工作中遇到的几种黑屏情况做下记录,然后供以后解决问题做参考 2.首次开…

Java String之正则表达式

Java String之正则表达式 导言 最近做项目时&#xff0c;遇到了限制输入字符格式的问题&#xff0c;采用了Java String的正则表达式&#xff0c;下面针对正则表达式使用进行概述 正则表达式 正则表达式类似可以通俗的理解为字符模板&#xff0c;通过符号的方式进行表述&…

uni-app--》基于小程序开发的电商平台项目实战(五)

&#x1f3cd;️作者简介&#xff1a;大家好&#xff0c;我是亦世凡华、渴望知识储备自己的一名在校大学生 &#x1f6f5;个人主页&#xff1a;亦世凡华、 &#x1f6fa;系列专栏&#xff1a;uni-app &#x1f6b2;座右铭&#xff1a;人生亦可燃烧&#xff0c;亦可腐败&#xf…

Fetch与Axios数据请求

什么是Polyfill? Polyfill是一个js库&#xff0c;主要抚平不同浏览器之间对js实现的差异。比如&#xff0c;html5的storage(session,local), 不同浏览器&#xff0c;不同版本&#xff0c;有些支持&#xff0c;有些不支持。Polyfill&#xff08;Polyfill有很多&#xff0c;在Gi…

IDEA spring-boot项目启动,无法加载或找到启动类问题解决

问题描述&#xff1a;找不到或无法加载主类 xxx.xxx.xxx.Classname 解决方案&#xff1a; 1.检查启动设置&#xff1a; 启动类所在包运行环境&#xff08;一般选择默认即可&#xff09;设置完成即可进行运行测试 2.如果第一步没有解决问题&#xff0c;试着第二步&#xff1a…

常见三维建模软件有哪些?各自的特点是什么?

常见的三维建模软件包括以下这些&#xff1a; 1. 3DS Max 3D Studio Max&#xff0c;简称3DS MAX&#xff0c;是当今世界上销售量最大的三维建模、动画及渲染软件。它的应用范围广泛&#xff0c;包括计算机游戏中的动画制作、影视片的特效制作等。3DS MAX的操作相对容易&#…

【学习笔记】RabbitMQ02:交换机,以及结合springboot快速开始

参考资料 RabbitMQ官方网站RabbitMQ官方文档噼咔噼咔-动力节点教程 文章目录 四、RabbitMQ &#xff1a;Exchange 交换机4.1 交换机类型4.2 扇形交换机 Fanout Exchange4.2.1 概念4.2.1 实例&#xff1a;生产者4.2.1.1 添加起步依赖4.2.1.2 配置文件4.2.1.3 JavaBean进行配置4.…

iMazing 3中文版功能介绍免费下载安装教程

iMazing 3中文版免费下载是一款兼容Win和Mac的iOS设备管理软件。iMazing 3能够将音乐、文件、消息和应用等数据从任何 iPhone、iPad 或 iPod 传输到 Mac 或 PC 上。 使用iMazing 3独特的 iOS 备份功能保证数据安全:设定自动无线备份时间并支持快照;将备份保存到外接驱动器和网…