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

相关文章

MySQL中的LENGTH()函数用法详解与实例分析

《MySQL中的LENGTH()函数用法详解与实例分析》MySQLLENGTH()函数用于计算字符串的字节长度,区别于CHAR_LENGTH()的字符长度,适用于多字节字符集(如UTF-8)的数据验证... 目录1. LENGTH()函数的基本语法2. LENGTH()函数的返回值2.1 示例1:计算字符串

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景

python中Hash使用场景分析

《python中Hash使用场景分析》Python的hash()函数用于获取对象哈希值,常用于字典和集合,不可变类型可哈希,可变类型不可,常见算法包括除法、乘法、平方取中和随机数哈希,各有优缺点,需根... 目录python中的 Hash除法哈希算法乘法哈希算法平方取中法随机数哈希算法小结在Python中,

Java Stream的distinct去重原理分析

《JavaStream的distinct去重原理分析》Javastream中的distinct方法用于去除流中的重复元素,它返回一个包含过滤后唯一元素的新流,该方法会根据元素的hashcode和eq... 目录一、distinct 的基础用法与核心特性二、distinct 的底层实现原理1. 顺序流中的去重

关于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地址三