《算法题讲解指南:优选算法-模拟》--41.外观数列,42.数青蛙

《算法题讲解指南:优选算法-模拟》--41.外观数列,42.数青蛙

🔥小叶-duck个人主页

❄️个人专栏《Data-Structure-Learning》

《C++入门到进阶&自我学习过程记录》《算法题讲解指南》--从优选到贪心

未择之路,不须回头
已择之路,纵是荆棘遍野,亦作花海遨游


目录

41.外观数列

题目链接:

题目描述:

题目示例:

解法(模拟):

算法思路:

C++算法代码:

算法总结及流程解析:

42.数青蛙

题目链接:

题目描述:

题目示例:

解法(模拟+分情况讨论):

算法思路:

C++算法代码:

算法总结及流程解析:

结束语


41.外观数列

题目链接:

38. 外观数列 - 力扣(LeetCode)

题目描述:

题目示例:

解法(模拟):

算法思路:

      所谓【外观数列】,其中只是依次统计字符串中连续且相同的字符的个数。依据题意,依次模拟即可。

C++算法代码:

class Solution { public: // string func(string s) // { // string ret; // int left = 0, right = 0, len = 0; // while(right < s.size()) // { // if(s[right] == s[left]) // { // right++; // } // else // { // len = right - left; // ret += to_string(len); // ret += s[left]; // left = right; // } // } // len = right - left; // ret += to_string(len); // ret += s[left]; // return ret; // } string countAndSay(int n) { // string ret = "1"; // while(--n) // { // ret = func(ret); // } // return ret; string ret = "1"; while(--n) { string s; //巧妙用一下双指针来获取相同数字的长度 int left = 0, right = 0, len = 0; while(right < ret.size()) { if(ret[right] == ret[left]) { right++; } else { len = right - left; s += to_string(len);//to_string可以将数字转换出字符 s += ret[left]; left = right; } } len = right - left; s += to_string(len); s += ret[left]; ret = s; } return ret; } };

算法总结及流程解析:

42.数青蛙

题目链接:

1419. 数青蛙 - 力扣(LeetCode)

题目描述:

题目示例:

解法(模拟+分情况讨论):

算法思路:

      模拟青蛙的叫声。

  • 当遇到 'r'  'o'  'a'  'k' 这四个字符的时候,我们要去看看每一个字符对应的前驱字符,有没有青蛙叫出来。如果有青蛙叫出来,那么就让这个青蛙接下来喊出这个字符;如果没有,直接返回 -1;
  • 当遇到 ‘c’ 这个字符的时候,我们去看看 ‘k’ 这个字符有没有青蛙叫出来。如果有,就让这个青蛙继续去 ‘c’ 这个字符;如果没有的话,就重新整一个青蛙出来

C++算法代码:

class Solution { public: int minNumberOfFrogs(string croakOfFrogs) { // //暴力算法:模拟 // //通过一个数组hash模拟存放croak这五个字母 // int n = croakOfFrogs.size(); // vector<int> hash(5, 0); // for(int i = 0; i < n; i++) // { // if(croakOfFrogs[i] == 'c') // { // if(hash[4]) // { // hash[4]--; // } // hash[0]++; // } // else if(croakOfFrogs[i] == 'r') // { // if(hash[0]-- == 0) // { // return -1; // } // hash[1]++; // } // else if(croakOfFrogs[i] == 'o') // { // if(hash[1]-- == 0) // { // return -1; // } // hash[2]++; // } // else if(croakOfFrogs[i] == 'a') // { // if(hash[2]-- == 0) // { // return -1; // } // hash[3]++; // } // else // { // if(hash[3]-- == 0) // { // return -1; // } // hash[4]++; // } // } // for(int i = 0; i < hash.size() - 1; i++) // { // if(hash[i] != 0) // { // return -1; // } // } // return hash[4]; //代码优化:使用一个哈希表存放croak在数组hash中对应的下标,便于快速访问 //就可以不用像上面那样用五个if else来分别判断 string s = "croak"; int n = s.size(); vector<int> hash(n, 0);//用数组模拟哈希表hash来存放croak几个字符 unordered_map<char, int> index; //存放字符所对应在数组hash中的下标 for(int i = 0; i < n; i++) { index[s[i]] = i; } for(int i = 0; i < croakOfFrogs.size(); i++) { int x = index[croakOfFrogs[i]]; //获取到当前字符的下标 if(x != 0) //当前字符为r、o、a、k { if(hash[x - 1]-- == 0) { return -1; } hash[x]++; } else//当前字符为c { if(hash[n - 1]) { hash[n - 1]--; } hash[x]++; } } //如果遍历完字符串后数组hash中除了最后一位k有值, //还有其他字符也有值,则说明有传声还没有完成,则返回-1 for(int i = 0; i < n - 1; i++) { if(hash[i] != 0) { return -1; } } return hash[n - 1]; } };

算法总结及流程解析:

结束语

      到此,41.外观数列,42.数青蛙 这两道算法题就讲解完了。外观数列:模拟统计连续相同字符的个数并生成新字符串。通过双指针计数,迭代n-1次得到结果。数青蛙:通过模拟青蛙叫声过程,分析字符序列croak的匹配逻辑。算法使用哈希表记录字符位置,并动态维护各阶段字符计数:当遇到c时复用已完成k的青蛙或新增青蛙;其他字符则需前驱字符存在才能继续。最后检查未完成序列的青蛙数量。希望大家能有所收获!

Read more

基于C++11手撸前端Promise

基于C++11手撸前端Promise

文章导航 * 引言 * 前端Promise的应用与优势 * 常见应用场景 * 并发请求 * Promise 解决的问题 * 手写 C++ Promise 实现 * 类结构与成员变量 * 构造函数 * resolve 方法 * reject 方法 * then 方法 * onCatch 方法 * 链式调用 * 使用示例 * `std::promise` 与 `CProimse` 对比 * 1. 基础功能对比 * 2. 实现细节对比 * (1) 状态管理 * (2) 回调注册与执行 * (3) 异步支持 * (4) 链式调用 * 3. 代码示例对比 * (1) `CProimse` 示例 * (2) `std::promise` 示例 * 4.

By Ne0inhk
❿⁄₁₃ ⟦ OSCP ⬖ 研记 ⟧ 密码攻击实践 ➱ 获取并破解Net-NTLMv2哈希(下)

❿⁄₁₃ ⟦ OSCP ⬖ 研记 ⟧ 密码攻击实践 ➱ 获取并破解Net-NTLMv2哈希(下)

郑重声明:本文所涉安全技术仅限用于合法研究与学习目的,严禁任何形式的非法利用。因不当使用所导致的一切法律与经济责任,本人概不负责。任何形式的转载均须明确标注原文出处,且不得用于商业目的。 🔋 点赞 | 能量注入 ❤️ 关注 | 信号锁定 🔔 收藏 | 数据归档 ⭐️ 评论 | 保持连接💬 🌌 立即前往 👉晖度丨安全视界🚀 ▶ 信息收集  ▶ 漏洞检测 ▶ 初始立足点  ▶ 权限提升 ▶ 横向移动 ➢ 密码攻击 ➢  获取并破解Net-NTLMv2哈希(下)🔥🔥🔥 ▶ 报告/分析 ▶ 教训/修复 目录 1.密码破解 1.1 破解Windows哈希实践 1.1.3 捕获Net-NTLMv2哈希实践 1.1.3.3 使用Netcat连接绑定 Shell(kali上) 1.连接流程 2.连接命令

By Ne0inhk
剑指offer第2版:链表系列

剑指offer第2版:链表系列

一、p58-JZ6 从尾到头打印链表(递归/栈) 从尾到头打印链表_牛客题霸_牛客网  解法1、递归,每访问一个节点时,先递归输出它后面的节点,再输出该节点自身,但是这样的话可能导致函数的调用层级很深,从而导致函数调用栈溢出。 class Solution { public: void print(vector<int>&ret,ListNode* head){ if(head==nullptr) return; print(ret,head->next); ret.emplace_back(head->val); } vector<int> printListFromTailToHead(ListNode* head)

By Ne0inhk
Welford 算法 | 优雅地计算海量数据的均值与方差

Welford 算法 | 优雅地计算海量数据的均值与方差

当内存装不下数据时 在机器学习特征工程或数据分析中,我们经常遇到这样的场景:手头有成百上千个独立的特征文件(CSV、Parquet 或 Numpy 格式),总量达到了几百 GB 甚至 TB 级别。现在需要计算这些特征的全局统计量(平均值、方差、标准差)来进行归一化(Standardization)。然而,开发机内存只有 16GB。如果尝试简单的 pandas.read_csv() 或 numpy.concatenate() 把所有数据读入内存,程序会瞬间 OOM(Out of Memory)崩溃。面对据量 >> 内存的场景,我们需要一种流式(Streaming)或增量(Incremental)的计算方案——Welford 算法。 教科书公式的陷阱 在统计学教科书中,

By Ne0inhk