leetcode解题思路分析(九十八)846 - 852 题

2024-09-05 04:48

本文主要是介绍leetcode解题思路分析(九十八)846 - 852 题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  1. 一手顺子
    爱丽丝有一手(hand)由整数数组给定的牌。 现在她想把牌重新排列成组,使得每个组的大小都是 W,且由 W 张连续的牌组成。如果她可以完成分组就返回 true,否则返回 false。

记录每个牌是否用过,排序后依次找即可

class Solution {
public:bool isNStraightHand(vector<int>& hand, int groupSize) {int len = hand.size();// 两种特例if(len % groupSize != 0) return false; // 不能整除 直接返回falseif(groupSize == 1) return true; // groupSize为1 直接返回true// 排序sort(hand.begin(),hand.end());// 记录数组元素是否被用过vector<int> used(len,false);// i为第一个指针 遍历hand数组 for(int i=0;i<len;i++){// 元素已被使用则跳过if(used[i]) continue;// 剩下的牌数量不足以构成一个新的Wif(i>len-groupSize) return false;// 取use[i]为这一手牌中的第一张牌 并记录该牌已被使用int cur = hand[i];            used[i] = true;int tar = cur + 1; // tar为下一张需要找到的牌int end = cur + groupSize - 1;// end为这一手牌中的最后一张牌for(int j=i+1;j<len;j++){if(used[j]) continue; // 若已被用过 则跳过if(hand[j]>tar) return false;// hand[j]>tar 说明缺少需要的牌else if(hand[j]==tar){// hand[j]==tar 说明已找到下一张需要的牌used[j] = true;if(hand[j]==end)break; // 已找到end这张牌 跳出循环 重新开始找新的一组牌// 还未到end 继续找下一个tarelse tar++;}}}return true;}
};
  1. 访问所有节点的最短路径
    存在一个由 n 个节点组成的无向连通图,图中的节点按从 0 到 n - 1 编号。给你一个数组 graph 表示这个图。其中,graph[i] 是一个列表,由所有与节点 i 直接相连的节点组成。返回能够访问所有节点的最短路径的长度。你可以在任一节点开始和停止,也可以多次重访节点,并且可以重用边

采用BFS+状态压缩得解

class Solution {
public:int shortestPathLength(vector<vector<int>>& graph) {int n = graph.size();// 1.初始化队列及标记数组,存入起点queue< tuple<int, int, int> > q; // 三个属性分别为 idx, mask, distvector<vector<bool>> vis(n, vector<bool>(1 << n)); // 节点编号及当前状态for(int i = 0; i < n; i++) {q.push({i, 1 << i, 0}); // 存入起点,起始距离0,标记vis[i][1 << i] = true;}// 开始搜索while(!q.empty()) {auto [cur, mask, dist] = q.front(); // 弹出队头元素q.pop();// 找到答案,返回结果if(mask == (1 << n) - 1) return dist;// 扩展for(int x : graph[cur]) {int nextmask = mask | (1 << x);if(!vis[x][nextmask]) {q.push({x, nextmask, dist + 1});vis[x][nextmask] = true;}}}return 0;}
};
  1. 字母移位
    有一个由小写字母组成的字符串 S,和一个整数数组 shifts。我们将字母表中的下一个字母称为原字母的 移位(由于字母表是环绕的, ‘z’ 将会变成 ‘a’)。例如·,shift(‘a’) = ‘b’, shift(‘t’) = ‘u’,, 以及 shift(‘z’) = ‘a’。对于每个 shifts[i] = x , 我们会将 S 中的前 i+1 个字母移位 x 次。返回将所有这些移位都应用到 S 后最终得到的字符串。

前缀和的使用

class Solution {
public:string shiftingLetters(string s, vector<int>& shifts) {vector<int>presum;long long sumall=shifts.back();presum.push_back(sumall);reverse(shifts.begin(),shifts.end());for(int i=1;i<shifts.size();i++){sumall%=26;sumall+=shifts[i];sumall%=26;presum.push_back(sumall);}reverse(presum.begin(),presum.end());//cout<<presum[2]<<endl;for(int i=0;i<s.size();i++){int inter=presum[i]%26;int index=s[i]-'a';s[i]=(inter+index)%26+'a';}return s;}
};
  1. 到最近的人的最大距离
    给你一个数组 seats 表示一排座位,其中 seats[i] = 1 代表有人坐在第 i 个座位上,seats[i] = 0 代表座位 i 上是空的(下标从 0 开始)。至少有一个空座位,且至少有一人已经坐在座位上。亚历克斯希望坐在一个能够使他与离他最近的人之间的距离达到最大化的座位上。返回他到离他最近的人的最大距离。

双指针滑动解题

class Solution {
public:int maxDistToClosest(vector<int>& seats) {int pre = -1;   //上一个已坐位置,初始值为-1int maxdis = 0; //两个已坐位置间的最大长度int n = seats.size();for (int i = 0; i < n; i++) {if (seats[i] == 1) {    //已坐座位//第一个已坐座位if (pre == -1) {maxdis = i * 2;}else if (i - pre > 1) {maxdis = max(maxdis, i - pre - 1);}pre = i;    //更新pre}//非已坐座位且是最后一个座位else if (i == n - 1) {maxdis = max(maxdis, 2 * (i - pre));}}return maxdis - maxdis / 2; //离他最近的人的最大距离为maxdis - maxdis / 2}
};
  1. 矩形面积2
    我们给出了一个(轴对齐的)矩形列表 rectangles 。 对于 rectangle[i] = [x1, y1, x2, y2],其中(x1,y1)是矩形 i 左下角的坐标,(x2,y2)是该矩形右上角的坐标。找出平面中所有矩形叠加覆盖后的总面积。 由于答案可能太大,请返回它对 10 ^ 9 + 7 取模的结果。

线性扫描

class Solution 
{
private:const static int MOD = 1e9 + 7;const static int OPEN = 0;const static int CLOSE = 1;// 计算宽度:其实就是不断累加更大的x的差值即可int QueryWidth(multiset<pair<int,int>>& activate){int res = 0;int maxX = -1;for (auto [x1, x2] : activate){maxX = max(maxX, x1);// 如果x变大了,则计算差值累加更大的宽度res += max(0, x2 - maxX);// 不断更新最大xmaxX = max(maxX, x2);}return res;}public:int rectangleArea(vector<vector<int>>& rectangles) {vector<vector<int>> rec;for (auto v: rectangles){rec.push_back({v[1], OPEN, v[0], v[2]});rec.push_back({v[3], CLOSE, v[0], v[2]});}// 排序从下到上来扫描sort(rec.begin(), rec.end());// 存储面积和int res = 0;// 初始化第一个y的位置int lastY = rec[0][0];// 当前需要计算的面积横坐标 [x1,x2]// 扫描过程中 对于每次OPEN则插入,CLOSE则删除multiset<pair<int,int>> activate;for (const vector<int> r : rec){int y = r[0];int state = r[1];int x1 = r[2];int x2 = r[3];// 累加面积res = (res + (long long)QueryWidth(activate)*(y-lastY)) % MOD;// 更新上一个y坐标lastY = y;// 对于每次OPEN则插入,CLOSE则删除if (state == OPEN){activate.insert({x1, x2});}else{activate.erase(activate.find(pair<int,int>{x1, x2}) );}}return res;}
};
  1. 喧闹和富有
    在一组 N 个人(编号为 0, 1, 2, …, N-1)中,每个人都有不同数目的钱,以及不同程度的安静(quietness)。为了方便起见,我们将编号为 x 的人简称为 "person x "。如果能够肯定 person x 比 person y 更有钱的话,我们会说 richer[i] = [x, y] 。注意 richer 可能只是有效观察的一个子集。另外,如果 person x 的安静程度为 q ,我们会说 quiet[x] = q 。现在,返回答案 answer ,其中 answer[x] = y 的前提是,在所有拥有的钱不少于 person x 的人中,person y 是最安静的人(也就是安静值 quiet[y] 最小的人)。

根据有钱程度进行排序,然后再比较安静值得出最终解。

class Solution {
public:vector<int> loudAndRich(vector<vector<int>>& richer, vector<int>& quiet) {int n = quiet.size();vector<vector<int>> g(n);//有向图,富的指向穷的vector<int> indegree(n, 0);//入度for(auto& r : richer){g[r[0]].push_back(r[1]);indegree[r[1]]++;}queue<int> q;//点的idvector<int> ans(n, -1);for(int i = 0; i< n; i++)ans[i] = i;//初始化最安静的是自己for(int i = 0; i < n; i++){if(indegree[i] == 0){q.push(i);//最富裕的人,入度为0}}while(!q.empty()){int id = q.front();//人的idint q_val = quiet[ans[id]];//到他这为止,最安静的人的安静值q.pop();for(auto nt : g[id])//跟他连接的人(比他穷){if(q_val < quiet[ans[nt]])//比 nt 更安静的人是 ans[nt], 其安静值没有q_val小ans[nt] = ans[id];if(--indegree[nt] == 0)q.push(nt);}}return ans;}
};
  1. 山脉数组的峰顶索引
    符合下列属性的数组 arr 称为 山脉数组 :
    arr.length >= 3
    存在 i(0 < i < arr.length - 1)使得:
    arr[0] < arr[1] < … arr[i-1] < arr[i]
    arr[i] > arr[i+1] > … > arr[arr.length - 1]
    给你由整数组成的山脉数组 arr ,返回任何满足 arr[0] < arr[1] < … arr[i - 1] < arr[i] > arr[i + 1] > … > arr[arr.length - 1] 的下标 i 。

二分查找

class Solution {
public:int peakIndexInMountainArray(vector<int>& arr) {int size = arr.size();int left = 0, right = size, mid = 0, ret = 0;while (left < right){mid = (left + right) / 2;if (arr[mid] > arr[mid + 1]){if (arr[mid] > arr[mid - 1]){ret = mid;break;}right = mid;continue;}else{left = mid;}}return ret;}
};

这篇关于leetcode解题思路分析(九十八)846 - 852 题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1137990

相关文章

关于MyISAM和InnoDB对比分析

《关于MyISAM和InnoDB对比分析》:本文主要介绍关于MyISAM和InnoDB对比分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录开篇:从交通规则看存储引擎选择理解存储引擎的基本概念技术原理对比1. 事务支持:ACID的守护者2. 锁机制:并发控制的艺

MyBatis Plus 中 update_time 字段自动填充失效的原因分析及解决方案(最新整理)

《MyBatisPlus中update_time字段自动填充失效的原因分析及解决方案(最新整理)》在使用MyBatisPlus时,通常我们会在数据库表中设置create_time和update... 目录前言一、问题现象二、原因分析三、总结:常见原因与解决方法对照表四、推荐写法前言在使用 MyBATis

Python主动抛出异常的各种用法和场景分析

《Python主动抛出异常的各种用法和场景分析》在Python中,我们不仅可以捕获和处理异常,还可以主动抛出异常,也就是以类的方式自定义错误的类型和提示信息,这在编程中非常有用,下面我将详细解释主动抛... 目录一、为什么要主动抛出异常?二、基本语法:raise关键字基本示例三、raise的多种用法1. 抛

github打不开的问题分析及解决

《github打不开的问题分析及解决》:本文主要介绍github打不开的问题分析及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、找到github.com域名解析的ip地址二、找到github.global.ssl.fastly.net网址解析的ip地址三

Mysql的主从同步/复制的原理分析

《Mysql的主从同步/复制的原理分析》:本文主要介绍Mysql的主从同步/复制的原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录为什么要主从同步?mysql主从同步架构有哪些?Mysql主从复制的原理/整体流程级联复制架构为什么好?Mysql主从复制注意

java -jar命令运行 jar包时运行外部依赖jar包的场景分析

《java-jar命令运行jar包时运行外部依赖jar包的场景分析》:本文主要介绍java-jar命令运行jar包时运行外部依赖jar包的场景分析,本文给大家介绍的非常详细,对大家的学习或工作... 目录Java -jar命令运行 jar包时如何运行外部依赖jar包场景:解决:方法一、启动参数添加: -Xb

Apache 高级配置实战之从连接保持到日志分析的完整指南

《Apache高级配置实战之从连接保持到日志分析的完整指南》本文带你从连接保持优化开始,一路走到访问控制和日志管理,最后用AWStats来分析网站数据,对Apache配置日志分析相关知识感兴趣的朋友... 目录Apache 高级配置实战:从连接保持到日志分析的完整指南前言 一、Apache 连接保持 - 性

Linux中的more 和 less区别对比分析

《Linux中的more和less区别对比分析》在Linux/Unix系统中,more和less都是用于分页查看文本文件的命令,但less是more的增强版,功能更强大,:本文主要介绍Linu... 目录1. 基础功能对比2. 常用操作对比less 的操作3. 实际使用示例4. 为什么推荐 less?5.

spring-gateway filters添加自定义过滤器实现流程分析(可插拔)

《spring-gatewayfilters添加自定义过滤器实现流程分析(可插拔)》:本文主要介绍spring-gatewayfilters添加自定义过滤器实现流程分析(可插拔),本文通过实例图... 目录需求背景需求拆解设计流程及作用域逻辑处理代码逻辑需求背景公司要求,通过公司网络代理访问的请求需要做请

Java集成Onlyoffice的示例代码及场景分析

《Java集成Onlyoffice的示例代码及场景分析》:本文主要介绍Java集成Onlyoffice的示例代码及场景分析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要... 需求场景:实现文档的在线编辑,团队协作总结:两个接口 + 前端页面 + 配置项接口1:一个接口,将o