leetcode解题思路分析(一百零三)881 - 887 题

2024-09-05 04:48

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

  1. 救生艇
    第 i 个人的体重为 people[i],每艘船可以承载的最大重量为 limit。每艘船最多可同时载两人,但条件是这些人的重量之和最多为 limit。返回载到每一个人所需的最小船数。(保证每个人都能被船载)。

贪心算法:双指针滑动,如果最轻+最重可以坐得下,则一起走,否则把最重的人先驮走

class Solution {
public:int numRescueBoats(vector<int> &people, int limit) {int ans = 0;sort(people.begin(), people.end());int light = 0, heavy = people.size() - 1;while (light <= heavy) {if (people[light] + people[heavy] > limit) {--heavy;} else {++light;--heavy;}++ans;}return ans;}
};
  1. 细分图中的可到达结点
    给你一个无向图(原始图),图中有 n 个节点,编号从 0 到 n - 1 。你决定将图中的每条边细分为一条节点链,每条边之间的新节点数各不相同。现在得到一个新的 细分图 ,请你计算从节点 0 出发,可以到达多少个节点?节点 是否可以到达的判断条件 为:如果节点间距离是 maxMoves 或更少,则视为可以到达;否则,不可到达。给你原始图和 maxMoves ,返回新的细分图中从节点 0 出发 可到达的节点数 。

dijkstra算法

#define pii pair<int, int>class Solution {
public:int reachableNodes(vector<vector<int>>& edges, int M, int N) {vector<vector<pii>> graph(N);for (vector<int> edge: edges) {int u = edge[0], v = edge[1], w = edge[2];graph[u].push_back({v, w});graph[v].push_back({u, w});}map<int, int> dist;dist[0] = 0;for (int i = 1; i < N; ++i)dist[i] = M+1;map<pii, int> used;int ans = 0;priority_queue<pii, vector<pii>, greater<pii>> pq;pq.push({0, 0});while (!pq.empty()) {pii top = pq.top();pq.pop();int d = top.first, node = top.second;if (d > dist[node]) continue;dist[node] = d;// Each node is only visited once.  We've reached// a node in our original graph.ans++;for (auto pair: graph[node]) {// M - d is how much further we can walk from this node;// weight is how many new nodes there are on this edge.// v is the maximum utilization of this edge.int nei = pair.first;int weight = pair.second;used[{node, nei}] = min(weight, M - d);// d2 is the total distance to reach 'nei' (nei***or) node// in the original graph.int d2 = d + weight + 1;if (d2 < min(dist[nei], M+1)) {pq.push({d2, nei});dist[nei] = d2;}}}// At the end, each edge (u, v, w) can be used with a maximum// of w new nodes: a max of used[u, v] nodes from one side,// and used[v, u] nodes from the other.for (vector<int> edge: edges) {int u = edge[0], v = edge[1], w = edge[2];ans += min(w, used[{u, v}] + used[{v, u}]);}return ans;}
};
  1. 三维形体投影面积
    在 N * N 的网格中,我们放置了一些与 x,y,z 三轴对齐的 1 * 1 * 1 立方体。每个值 v = grid[i][j] 表示 v 个正方体叠放在单元格 (i, j) 上。现在,我们查看这些立方体在 xy、yz 和 zx 平面上的投影。投影就像影子,将三维形体映射到一个二维平面上。在这里,从顶部、前面和侧面看立方体时,我们会看到“影子”。返回所有三个投影的总面积。

从顶部看,由该形状生成的阴影将是网格中非零值的数目。从侧面看,由该形状生成的阴影将是网格中每一行的最大值。从前面看,由该形状生成的阴影将是网格中每一列的最大值。

class Solution {
public:int projectionArea(vector<vector<int>>& grid) {int N = grid.size();int ans = 0;for (int i = 0; i < N;  ++i) {int bestRow = 0;  // largest of grid[i][j]int bestCol = 0;  // largest of grid[j][i]for (int j = 0; j < N; ++j) {if (grid[i][j] > 0) ans++;  // top shadowbestRow = max(bestRow, grid[i][j]);bestCol = max(bestCol, grid[j][i]);}ans += bestRow + bestCol;}return ans;}
};
  1. 两句话中的不常见单词
    句子 是一串由空格分隔的单词。每个 单词 仅由小写字母组成。如果某个单词在其中一个句子中恰好出现一次,在另一个句子中却 没有出现 ,那么这个单词就是 不常见的 。给你两个 句子 s1 和 s2 ,返回所有 不常用单词 的列表。返回列表中单词可以按 任意顺序 组织。

字符串拼接

class Solution {
public:vector<string> uncommonFromSentences(string s1, string s2) {std::vector<string> ret;std::map<string, int>::iterator iter;WordsCount(s1);WordsCount(s2);for (iter = m_map.begin(); iter != m_map.end(); ++iter){if (iter->second == 1){ret.push_back(iter->first);}}return ret;}void WordsCount(string s){int pos = 0, cnt = 0;for (int i = 0; i < s.size(); ++i){if (s[i] == ' '){string sub = s.substr(pos, cnt);pos = i + 1;cnt = 0;m_map[sub]++;}else{cnt++;}}string sub = s.substr(pos, cnt);m_map[sub]++;}private:std::map<string, int> m_map;
};
  1. 螺旋矩阵 III
    在 R 行 C 列的矩阵上,我们从 (r0, c0) 面朝东面开始这里,网格的西北角位于第一行第一列,网格的东南角位于最后一行最后一列。现在,我们以顺时针按螺旋状行走,访问此网格中的每个位置。每当我们移动到网格的边界之外时,我们会继续在网格之外行走(但稍后可能会返回到网格边界)。最终,我们到过网格的所有 R * C 个空间。按照访问顺序返回表示网格位置的坐标列表。

读懂题意照着走就完事

class Solution {
public:vector<vector<int>> spiralMatrixIII(int R, int C, int r0, int c0) {vector<vector<int>> res;vector<pair<int, int>> around = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};  //顺时针方向int x = r0, y = c0, num = 1, dir = 0;  //{x, y}为当前位置,num为当前查找的数字,dir为当前的方向int Left = c0 - 1, Right = c0 + 1, Upper = r0 - 1, Bottom = r0 + 1;  //四个方向的边界while (num <= R * C) {if (x >= 0 && x < R && y >= 0 && y < C) {  //{x, y}位置在矩阵中res.push_back({x, y});num += 1;}if (dir == 0 && y == Right) {  //向右到右边界dir += 1;  //调转方向向下Right += 1;  //右边界右移}else if (dir == 1 &&  x == Bottom) {  //向下到底边界dir += 1;Bottom += 1;  //底边界下移}else if (dir == 2 && y == Left) {  //向左到左边界dir += 1;Left--;  //左边界左移}else if (dir == 3 && x == Upper) {  //向上到上边界dir = 0;Upper--;  //上边界上移}x += around[dir].first;   //下一个节点y += around[dir].second;}return res;}
};
  1. 可能的二分法
    给定一组 N 人(编号为 1, 2, …, N), 我们想把每个人分进任意大小的两组。每个人都可能不喜欢其他人,那么他们不应该属于同一组。形式上,如果 dislikes[i] = [a, b],表示不允许将编号为 a 和 b 的人归入同一组。当可以用这种方法将所有人分进两组时,返回 true;否则返回 false。

转化为图的问题,或者用集合存放并查找

class Solution {
public:bool paint(int x, int c, vector<vector<int>>& edges, vector<int>& colors) {if (colors[x] == c) return true;else if (colors[x] != 0 && colors[x] != c) return false;colors[x] = c;int reversed = (c == 1 ? 2 : 1);for (auto& e : edges[x]) {if (!paint(e, reversed, edges, colors)) {colors[x] = 0;return false;}}return true;}bool possibleBipartition(int N, vector<vector<int>>& dislikes) {vector<vector<int>> edges(N);for (auto e : dislikes) {edges[e[0]-1].push_back(e[1]-1);}vector<int> colors(N, 0);for (int i = 0; i < N; ++i) {if(!paint(i, 1, edges, colors) && !paint(i, 2, edges, colors)) {return false;}}return true;}
};
  1. 鸡蛋掉落
    给你 k 枚相同的鸡蛋,并可以使用一栋从第 1 层到第 n 层共有 n 层楼的建筑。已知存在楼层 f ,满足 0 <= f <= n ,任何从 高于 f 的楼层落下的鸡蛋都会碎,从 f 楼层或比它低的楼层落下的鸡蛋都不会破。每次操作,你可以取一枚没有碎的鸡蛋并把它从任一楼层 x 扔下(满足 1 <= x <= n)。如果鸡蛋碎了,你就不能再次使用它。如果某枚鸡蛋扔下后没有摔碎,则可以在之后的操作中 重复使用 这枚鸡蛋。请你计算并返回要确定 f 确切的值 的 最小操作次数 是多少?

经典动态规划问题,也可以反向思维考虑t次操作、k个鸡蛋最多能到多少层楼

class Solution {
public:int superEggDrop(int k, int n) {if (n == 1) {return 1;}vector<vector<int>> f(n + 1, vector<int>(k + 1));for (int i = 1; i <= k; ++i) {f[1][i] = 1;}int ans = -1;for (int i = 2; i <= n; ++i) {for (int j = 1; j <= k; ++j) {f[i][j] = 1 + f[i - 1][j - 1] + f[i - 1][j];}if (f[i][k] >= n) {ans = i;break;}}return ans;}
};

这篇关于leetcode解题思路分析(一百零三)881 - 887 题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

慢sql提前分析预警和动态sql替换-Mybatis-SQL

《慢sql提前分析预警和动态sql替换-Mybatis-SQL》为防止慢SQL问题而开发的MyBatis组件,该组件能够在开发、测试阶段自动分析SQL语句,并在出现慢SQL问题时通过Ducc配置实现动... 目录背景解决思路开源方案调研设计方案详细设计使用方法1、引入依赖jar包2、配置组件XML3、核心配

Java NoClassDefFoundError运行时错误分析解决

《JavaNoClassDefFoundError运行时错误分析解决》在Java开发中,NoClassDefFoundError是一种常见的运行时错误,它通常表明Java虚拟机在尝试加载一个类时未能... 目录前言一、问题分析二、报错原因三、解决思路检查类路径配置检查依赖库检查类文件调试类加载器问题四、常见

Python中的Walrus运算符分析示例详解

《Python中的Walrus运算符分析示例详解》Python中的Walrus运算符(:=)是Python3.8引入的一个新特性,允许在表达式中同时赋值和返回值,它的核心作用是减少重复计算,提升代码简... 目录1. 在循环中避免重复计算2. 在条件判断中同时赋值变量3. 在列表推导式或字典推导式中简化逻辑

Java程序进程起来了但是不打印日志的原因分析

《Java程序进程起来了但是不打印日志的原因分析》:本文主要介绍Java程序进程起来了但是不打印日志的原因分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java程序进程起来了但是不打印日志的原因1、日志配置问题2、日志文件权限问题3、日志文件路径问题4、程序

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

Python 迭代器和生成器概念及场景分析

《Python迭代器和生成器概念及场景分析》yield是Python中实现惰性计算和协程的核心工具,结合send()、throw()、close()等方法,能够构建高效、灵活的数据流和控制流模型,这... 目录迭代器的介绍自定义迭代器省略的迭代器生产器的介绍yield的普通用法yield的高级用法yidle

Python获取C++中返回的char*字段的两种思路

《Python获取C++中返回的char*字段的两种思路》有时候需要获取C++函数中返回来的不定长的char*字符串,本文小编为大家找到了两种解决问题的思路,感兴趣的小伙伴可以跟随小编一起学习一下... 有时候需要获取C++函数中返回来的不定长的char*字符串,目前我找到两种解决问题的思路,具体实现如下:

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序

kotlin中const 和val的区别及使用场景分析

《kotlin中const和val的区别及使用场景分析》在Kotlin中,const和val都是用来声明常量的,但它们的使用场景和功能有所不同,下面给大家介绍kotlin中const和val的区别,... 目录kotlin中const 和val的区别1. val:2. const:二 代码示例1 Java

Go标准库常见错误分析和解决办法

《Go标准库常见错误分析和解决办法》Go语言的标准库为开发者提供了丰富且高效的工具,涵盖了从网络编程到文件操作等各个方面,然而,标准库虽好,使用不当却可能适得其反,正所谓工欲善其事,必先利其器,本文将... 目录1. 使用了错误的time.Duration2. time.After导致的内存泄漏3. jsO