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

leetcode解题思路分析(一百六十六)1438 - 1444 题

  1. 绝对差不超过限制的最长连续子数组
    给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit 。如果不存在满足条件的子数组,则返回 0 。

存储当前有序子数组的集合,采用滑动指针移动求出解

class Solution {
public:int longestSubarray(vector<int>& nums, int limit) {multiset<int> s;int n = nums.size();int left = 0, right = 0;int ret = 0;while (right < n) {s.insert(nums[right]);while (*s.rbegin() - *s.begin() > limit) {s.erase(s.find(nums[left++]));}ret = max(ret, right - left + 1);right++;}return ret;}
};
  1. 有序矩阵中的第 k 个最小数组和
    给你一个 m * n 的矩阵 mat,以及一个整数 k ,矩阵中的每一行都以非递减的顺序排列。你可以从每一行中选出 1 个元素形成一个数组。返回所有可能数组中的第 k 个 最小 数组和。

可以用小根堆或者二分查找来做

class Solution {
public:int kthSmallest(vector<vector<int>>& mat, int k) {int m = mat.size();vector<int> prev = mat[0];for (int i = 1; i < m; ++i) {prev = move(merge(prev, mat[i], k));}return prev[k - 1];}vector<int> merge(const vector<int>& f, const vector<int>& g, int k) {if (g.size() > f.size()) {return merge(g, f, k);}priority_queue<Entry> q;for (int i = 0; i < g.size(); ++i) {q.emplace(0, i, f[0] + g[i]);}vector<int> ans;while (k && !q.empty()) {Entry entry = q.top();q.pop();ans.push_back(entry.sum);if (entry.i + 1 < f.size()) {q.emplace(entry.i + 1, entry.j, f[entry.i + 1] + g[entry.j]);}--k;}return ans;}private:struct Entry {int i, j, sum;Entry(int _i, int _j, int _sum): i(_i), j(_j), sum(_sum) {}bool operator< (const Entry& that) const {return sum > that.sum;}};
};
  1. 用栈操作构建数组
    给你一个数组 target 和一个整数 n。
    给你一个空栈和两种操作:
    “Push”:将一个整数加到栈顶。
    “Pop”:从栈顶删除一个整数。
    同时给定一个范围 [1, n] 中的整数流。
    使用两个栈操作使栈中的数字(从底部到顶部)等于 target。

每次操作一个数字时,如果它在 target 中,则只需要将它 Push 入栈即可。如果不在 target 中,可以先将其 Push 入栈,紧接着 Pop 出栈。

class Solution {
public:vector<string> buildArray(vector<int>& target, int n) {vector<string> res;int prev = 0;for (int number : target) {for (int i = 0; i < number - prev - 1; i++) {res.emplace_back("Push");res.emplace_back("Pop");}res.emplace_back("Push");prev = number;}return res;}
};
  1. 形成两个异或相等数组的三元组数目
    给你一个整数数组 arr 。
    现需要从数组中取三个下标 i、j 和 k ,其中 (0 <= i < j <= k < arr.length) 。
    a 和 b 定义如下:
    a = arr[i] ^ arr[i + 1] ^ … ^ arr[j - 1]
    b = arr[j] ^ arr[j + 1] ^ … ^ arr[k]
    注意:^ 表示 按位异或 操作。
    请返回能够令 a == b 成立的三元组 (i, j , k) 的数目。

本题是前缀和的进阶版用法,异或前缀和。

class Solution {
public:int countTriplets(vector<int> &arr) {int n = arr.size();unordered_map<int, int> cnt, total;int ans = 0, s = 0;for (int k = 0; k < n; ++k) {int val = arr[k];if (cnt.count(s ^ val)) {ans += cnt[s ^ val] * k - total[s ^ val];}++cnt[s];total[s] += k;s ^= val;}return ans;}
};
  1. 收集树上所有苹果的最少时间
    给你一棵有 n 个节点的无向树,节点编号为 0 到 n-1 ,它们中有一些节点有苹果。通过树上的一条边,需要花费 1 秒钟。你从 节点 0 出发,请你返回最少需要多少秒,可以收集到所有苹果,并回到节点 0 。无向树的边由 edges 给出,其中 edges[i] = [fromi, toi] ,表示有一条边连接 from 和 toi 。除此以外,还有一个布尔数组 hasApple ,其中 hasApple[i] = true 代表节点 i 有一个苹果,否则,节点 i 没有苹果。

需要先做一次 DFS 求出每个点对应的子树上的苹果的数量,存入一个数组中,方便下面做 O(1) 的查询.在做好这些准备工作之后,我们再做一次 DFS 求解需要花费的最小时间

class Solution {
public:static constexpr int MAX_N = int(1E5) + 5;vector <int> g[MAX_N];int apple[MAX_N], ans;int getAppleNumber(int o, int from, vector<bool>& hasApple) {apple[o] = hasApple[o];for (const auto &son: g[o]) {if (son == from) {continue;}apple[o] += getAppleNumber(son, o, hasApple);} return apple[o];}void dfs(int o, int from) {for (const auto &son: g[o]) {if (son == from) {continue;}if (apple[son]) {ans += 2;dfs(son, o);}}}int minTime(int n, vector<vector<int>>& edges, vector<bool>& hasApple) {memset(apple, 0, sizeof apple);for (const auto &e: edges) {int u = e[0], v = e[1];g[u].push_back(v);g[v].push_back(u);}getAppleNumber(0, -1, hasApple);ans = 0;dfs(0, -1);return ans;}
};
  1. 切披萨的方案数
    给你一个 rows x cols 大小的矩形披萨和一个整数 k ,矩形包含两种字符: ‘A’ (表示苹果)和 ‘.’ (表示空白格子)。你需要切披萨 k-1 次,得到 k 块披萨并送给别人。切披萨的每一刀,先要选择是向垂直还是水平方向切,再在矩形的边界上选一个切的位置,将披萨一分为二。如果垂直地切披萨,那么需要把左边的部分送给一个人,如果水平地切,那么需要把上面的部分送给一个人。在切完最后一刀后,需要把剩下来的一块送给最后一个人。请你返回确保每一块披萨包含 至少 一个苹果的切披萨方案数。由于答案可能是个很大的数字,请你返回它对 10^9 + 7 取余的结果。

*动态规划解题

class Solution {
public:int ways(vector<string>& pizza, int k) {int m = pizza.size(), n = pizza[0].size(), mod = 1e9 + 7;vector<vector<int>> apples(m + 1, vector<int>(n + 1));vector<vector<vector<int>>> dp(k + 1, vector<vector<int>>(m + 1, vector<int>(n + 1)));// 预处理for (int i = m - 1; i >= 0; i--) {for (int j = n - 1; j >= 0; j--) {apples[i][j] = apples[i][j + 1] + apples[i + 1][j] - apples[i + 1][j + 1] + (pizza[i][j] == 'A');dp[1][i][j] = apples[i][j] > 0;}}for (int ki = 2; ki <= k; ki++) {for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {// 水平方向切for (int i2 = i + 1; i2 < m; i2++) {if (apples[i][j] > apples[i2][j]) {dp[ki][i][j] = (dp[ki][i][j] + dp[ki - 1][i2][j]) % mod;}}// 垂直方向切for (int j2 = j + 1; j2 < n; j2++) {if (apples[i][j] > apples[i][j2]) {dp[ki][i][j] = (dp[ki][i][j] + dp[ki - 1][i][j2]) % mod;}}}}}return dp[k][0][0];}
};
http://www.xdnf.cn/news/1411327.html

相关文章:

  • 【机器学习基础】无监督学习算法的现代演进:从数据探索到智能系统的自主发现能力
  • 深入理解Nginx反向代理及其应用
  • 京东商品评论接口技术实现:从接口分析到数据挖掘全方案
  • 【Android】Notification 的基本使用
  • [线上问题排查]深度剖析:一条MySQL慢查询的全面优化实战
  • Cesium 入门教程(十四):鼠标键盘交互
  • 设置Ubuntu 22.04 LTS上的rsync同步服务
  • 提取动漫图像轮廓并拟合为样条曲线(MATLAB)
  • WEB漏洞挖掘篇(一) 基本概念、十大常見WEB漏洞
  • Python训练营打卡Day49-神经网络调参指南
  • 赵玉平《刘备谋略》读书笔记(上部)
  • 如何通过 AI IDE 集成开发工具快速生成简易留言板系统
  • 链表OJ做题报告
  • 批量修改用户密码的命令chpasswd
  • 使用组合子构建抽象语法树
  • vsgCs显示谷歌全球倾斜模型-数据转换
  • 打工人日报#20250831
  • pyinstaller打包后失败问题记录
  • 贝叶斯分类(Bayes Classify)
  • Java面试-微服务(spring cloud篇)
  • 网络:相比于HTTP,HTTPS协议到底安全在哪?
  • 【HarmonyOS】天气预报 UI 的基本实现
  • 基于Echarts+HTML5可视化数据大屏展示-惠民服务平台
  • 一文理清TCP协议的通讯流程
  • 【车载开发系列】CAN与CANFD下篇
  • Linux-驱动积累
  • docker安装tomcat
  • 1.2 操作系统发展历程
  • dify docker compose操作命令指南
  • 【不懂就问】-手机相关学习