leetcode解题思路分析(五十)432 - 438 题

2024-09-05 04:58

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

  1. 全O(1)的数据结构

哈希表+链表即可

class AllOne {
public:/** Initialize your data structure here. */struct Node{unordered_set<string> container;int val = 0;Node(int v):val(v){}};unordered_map<string, list<Node>::iterator> kv;list<Node> List;AllOne() {}/** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */void inc(string key) {if(kv.count(key)){auto oldNode = kv[key];auto newNode = next(oldNode, 1);if(newNode == List.end() || newNode->val>oldNode->val+1){newNode = List.insert(newNode, Node(oldNode->val+1));}newNode->container.insert(key);oldNode->container.erase(key);if(oldNode->container.empty()){List.erase(oldNode);}kv[key] = newNode;} else {auto newNode = List.begin();if(List.empty() || List.begin()->val>1)newNode = List.insert(List.begin(), Node(1));newNode->container.insert(key);kv[key] = newNode;}}/** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */void dec(string key) {if(kv.count(key)){auto oldNode = kv[key];if(oldNode->val==1) {kv.erase(key);} else {auto newNode = next(oldNode, -1);if(oldNode==List.begin() || newNode->val<oldNode->val-1){newNode = List.insert(oldNode, Node(oldNode->val-1));}newNode->container.insert(key);kv[key] = newNode;}oldNode->container.erase(key);if(oldNode->container.empty()){List.erase(oldNode);}}}/** Returns one of the keys with maximal value. */string getMaxKey() {if(List.empty()) return "";return *List.rbegin()->container.begin();}/** Returns one of the keys with Minimal value. */string getMinKey() {if(List.empty()) return "";return *List.begin()->container.begin();}
};
  1. 最小基因变化
    现在给定3个参数 — start, end, bank,分别代表起始基因序列,目标基因序列及基因库,请找出能够使起始基因序列变化为目标基因序列所需的最少变化次数。如果无法实现目标变化,请返回 -1。

依次从基因库找变换一个字母可以构成的,然后删除基因库中的对应基因,继续查找直至找到或者找不到

class Solution {
public:int Dif_num(string& s1, string& s2){int cnt = 0;for (int i = 0; i < s1.size(); i++){if (s1[i] != s2[i])cnt++;}return cnt;}int minMutation(string start, string end, vector<string>& bank) {queue<string>qu;qu.push(start);int res = 0;unordered_map<string, int>vis;while (!qu.empty()){int size = qu.size();for (int i = 0; i < size; i++){string cur = qu.front();vis[cur] = 1;qu.pop();if (cur == end)return res;for (int i = 0; i < bank.size(); i++){if (Dif_num(cur, bank[i]) == 1 && !vis[bank[i]]){qu.push(bank[i]);}}}res++;}return -1;}
};
  1. 字符串中的单词数
    统计字符串中的单词个数,这里的单词指的是连续的不是空格的字符。

考察一个边界条件,十分简单了

class Solution {
public:int countSegments(string s) {int ret = 0;if (s.size() == 0) return ret;else if (s[0] != ' ') ret++;for (int i  = 0; i < s.size() - 1; i++){if (s[i] == ' ' && s[i + 1] != ' ') {ret++;i++;}}return ret;}
};
  1. 无重叠区间
    给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。

贪心算法的经典运用。先排序,然后挨个判断:如果包含关系则取小的,如果交错则抛弃后者,如果不相交则都存着

class Solution {
public:int eraseOverlapIntervals(vector<vector<int>>& intervals) {if (intervals.empty()) return 0;sort(intervals.begin(), intervals.end());int left = intervals[0][1];int res = 0;for (int i = 1; i < intervals.size(); ++i) {if (intervals[i][0] < left) {++res;left = min(left, intervals[i][1]);} else {left = intervals[i][1];}}return res;}
};
  1. 寻找右区间
    给定一组区间,对于每一个区间 i,检查是否存在一个区间 j,它的起始点大于或等于区间 i 的终点,这可以称为 j 在 i 的“右侧”。

分别存两份数组以区间起点和终点排序,然后进行比较得出右侧区间

// 利用两个数组,分别排序起点和终点位置
class Solution {
public:vector<int> findRightInterval(vector<vector<int>>& intervals) {vector<pair<int, int>> start;vector<pair<int, int>> end;int len = intervals.size();for(int i = 0; i < len; i++){start.push_back(make_pair(intervals[i][0], i));end.push_back(make_pair(intervals[i][1],i));}sort(start.begin(), start.end());sort(end.begin(), end.end(),[](pair<int, int> p1, pair<int, int> p2){if(p1.first == p2.first)return p1.second < p2.second;return p1.first < p2.first;//如果两个终点相同,会返回那个索引小的});vector<int> ans(len, -1);int indexS = 0;int indexE = 0;while(indexS < len && indexE < len){while(indexS < len && (start[indexS].second == end[indexE].second || start[indexS].first < end[indexE].first))indexS++;if(indexS < len)ans[end[indexE++].second] = start[indexS].second;}return ans;}
};
  1. 路径总和3
    给定一个二叉树,它的每个结点都存放着一个整数值。找出路径和等于给定数值的路径总数。

使用前缀和记录从而减小内存消耗,只需遍历一次树即可。

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:unordered_map<int, int> m;int sum, res = 0;
public:void dfs(TreeNode* root, int cur_sum){if (root == nullptr) return;if (m.count(cur_sum - sum))res += m[cur_sum - sum];m[cur_sum] ++;if (root->left)  dfs(root->left, cur_sum + root->left->val);if (root->right) dfs(root->right, cur_sum + root->right->val);m[cur_sum]--;}int pathSum(TreeNode* root, int sum) {if (root == nullptr) return 0;this->sum = sum;// 构建前缀和m[0] = 1;dfs(root, root->val);return res;}
};
  1. 找到字符串中所有字母异位词
    给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。

采用双指针滑动,用一个字典数组保存P的特征,滑动的过程中–,如果恰好为0且长度相等则说明找到了,否则滑动指针并++

class Solution {
public:vector<int> findAnagrams(string s, string p) {vector<int> res;int m[128] = {0};int left = 0, right = 0, need = 0;for (char c : p)++m[c];while (right < s.size()){if (m[s[right]] > 0)     ++need;--m[s[right]];++right;while (need == p.size()){if (right - left == p.size())   res.push_back(left);      //通过长度判断异位词,加入res中if (m[s[left]] == 0)     --need;++m[s[left]];++left;}}return res;}
};

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



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

相关文章

Nginx分布式部署流程分析

《Nginx分布式部署流程分析》文章介绍Nginx在分布式部署中的反向代理和负载均衡作用,用于分发请求、减轻服务器压力及解决session共享问题,涵盖配置方法、策略及Java项目应用,并提及分布式事... 目录分布式部署NginxJava中的代理代理分为正向代理和反向代理正向代理反向代理Nginx应用场景

Redis中的有序集合zset从使用到原理分析

《Redis中的有序集合zset从使用到原理分析》Redis有序集合(zset)是字符串与分值的有序映射,通过跳跃表和哈希表结合实现高效有序性管理,适用于排行榜、延迟队列等场景,其时间复杂度低,内存占... 目录开篇:排行榜背后的秘密一、zset的基本使用1.1 常用命令1.2 Java客户端示例二、zse

Redis中的AOF原理及分析

《Redis中的AOF原理及分析》Redis的AOF通过记录所有写操作命令实现持久化,支持always/everysec/no三种同步策略,重写机制优化文件体积,与RDB结合可平衡数据安全与恢复效率... 目录开篇:从日记本到AOF一、AOF的基本执行流程1. 命令执行与记录2. AOF重写机制二、AOF的

MyBatis Plus大数据量查询慢原因分析及解决

《MyBatisPlus大数据量查询慢原因分析及解决》大数据量查询慢常因全表扫描、分页不当、索引缺失、内存占用高及ORM开销,优化措施包括分页查询、流式读取、SQL优化、批处理、多数据源、结果集二次... 目录大数据量查询慢的常见原因优化方案高级方案配置调优监控与诊断总结大数据量查询慢的常见原因MyBAT

分析 Java Stream 的 peek使用实践与副作用处理方案

《分析JavaStream的peek使用实践与副作用处理方案》StreamAPI的peek操作是中间操作,用于观察元素但不终止流,其副作用风险包括线程安全、顺序混乱及性能问题,合理使用场景有限... 目录一、peek 操作的本质:有状态的中间操作二、副作用的定义与风险场景1. 并行流下的线程安全问题2. 顺

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

Java中最全最基础的IO流概述和简介案例分析

《Java中最全最基础的IO流概述和简介案例分析》JavaIO流用于程序与外部设备的数据交互,分为字节流(InputStream/OutputStream)和字符流(Reader/Writer),处理... 目录IO流简介IO是什么应用场景IO流的分类流的超类类型字节文件流应用简介核心API文件输出流应用文

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

Linux中的HTTPS协议原理分析

《Linux中的HTTPS协议原理分析》文章解释了HTTPS的必要性:HTTP明文传输易被篡改和劫持,HTTPS通过非对称加密协商对称密钥、CA证书认证和混合加密机制,有效防范中间人攻击,保障通信安全... 目录一、什么是加密和解密?二、为什么需要加密?三、常见的加密方式3.1 对称加密3.2非对称加密四、

MySQL中读写分离方案对比分析与选型建议

《MySQL中读写分离方案对比分析与选型建议》MySQL读写分离是提升数据库可用性和性能的常见手段,本文将围绕现实生产环境中常见的几种读写分离模式进行系统对比,希望对大家有所帮助... 目录一、问题背景介绍二、多种解决方案对比2.1 原生mysql主从复制2.2 Proxy层中间件:ProxySQL2.3