当前位置: 首页 > news >正文

每日算法(1)

每日算法(1)

数字统计

在这里插入图片描述

代码:(C++)

#include <iostream>using namespace std;int main()
{int l,r;cin>>l>>r;int ret=0;for(int i=l;i<=r;i++){int tmp=i;while(tmp){if(tmp%10==2) ret++;tmp/=10; }}cout<<ret<<endl;return 0;
}

简单直接的回答是:设置 tmp作为临时变量是为了在分解数字的每一位时,不破坏原始的循环变量 i

让我们用一个具体的例子来解释为什么这很重要:

举例说明

假设现在循环到 i = 123,我们要统计它里面有几个2。

    如果没有 tmp,直接操作 i

    while (i != 0) { // i 初始为 123if (i % 10 == 2) { // 检查个位数 3count++;}i = i / 10; // 问题就出在这里!i 被改成了 12
    }
    
    • •第一次循环后,i从 123 被除以10,变成了 12
    • •然后 for循环的 i++会让 i变成 13
    • 结果:数字 123 没有被完整检查(只检查了个位),并且整个循环序列被完全打乱了,直接跳过了 124, 125 等很多数字。最终结果肯定是错误的。

    使用 tmp作为临时变量(正确的做法):

    int tmp = i; // 创建 i 的副本
    while (tmp != 0) { // 对 tmp 进行操作,不影响 iif (tmp % 10 == 2) {count++;}tmp = tmp / 10; // 即使把 tmp 除以10变成0,原始的 i 也毫发无伤
    }
    
    • •我们只是在 tmp这个“副本”或“替身”上进行分解操作。
    • •无论 tmp如何变化,原始的循环变量 i始终保持不变,for循环可以正常地 i++,检查下一个数字。

总结

使用临时变量 tmp直接使用 i
保护数据:不破坏原始循环变量 i的值。破坏数据:修改了 i,导致循环失控。
逻辑清晰i负责遍历每个数,tmp负责分解每个数的各位,职责分明。逻辑混乱:一个变量 i承担了两个职责,互相干扰。
结果正确结果错误

所以,tmp的作用就是充当一个“替身”,代替原始数据去完成那些会破坏数据本身的操作,从而保证主流程的正确执行。 这是一个非常基础和重要的编程技巧。

两个数组的交集

在这里插入图片描述

a. 将其中⼀个数组丢进哈希表中;

b. 遍历另⼀个数组的时候,在哈希表中看看就好了

代码如下:

lass Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param nums1 int整型vector * @param nums2 int整型vector * @return int整型vector*/bool hash[1010]={0};vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {// write code herevector<int> ret;for(auto x:nums1){hash[x]=true;}for(auto x:nums2){if(hash[x]){ret.push_back(x);hash[x]=false;}}return ret;}
};

好的!这是一个非常关键的问题,它涉及到解决“数组交集”问题时一个常见的陷阱:如何避免结果中出现重复元素

核心原因:防止重复添加相同的元素

hash[x] = false;放在 if (hash[x])条件内部,是为了在将一个元素添加到结果数组后,立即将其标记为“已使用”,从而确保即使该元素在第二个数组 nums2中出现多次,也只会被添加到结果中一次。


逐步拆解逻辑

我们结合你给出的示例2来分析,这样会非常清晰:

输入:nums1 = [1, 2, 3], nums2 = [8, 2, 2, 3, 8]

    建立哈希表(第一阶段循环)

    // 遍历 nums1,将出现的数字标记为 true
    for (int num : nums1) {hash[num] = true;
    }
    

    执行后,哈希表的状态是:

    • hash[1] = true
    • hash[2] = true
    • hash[3] = true
    • •其他所有值都是 false

    查找交集并去重(第二阶段循环,关键步骤)

    for (int x : nums2) { // 遍历 nums2: [8, 2, 2, 3, 8]if (hash[x]) {    // 如果 x 在哈希表中为 true,说明它是交集元素result.push_back(x); // 将 x 加入结果hash[x] = false;    // 【关键】立即将其标记为 false}
    }
    

    我们来一步步看循环过程:

    • x = 8: hash[8]false-> 不执行if条件内的语句 -> 跳过
    • x = 2: hash[2]true-> 进入if条件内: •将 2加入结果数组 result。 •立即执行 hash[2] = false; (标记为已使用)。
    • x = 2: hash[2]现在已经是 false了 -> 不进入if条件 -> 跳过。这样就避免了第二个 2再次被加入结果。
    • x = 3: hash[3]true-> 进入if条件内: •将 3加入结果数组 result。 •立即执行 hash[3] = false;
    • x = 8: hash[8]false-> 跳过
  1. 3.最终结果: 结果数组 result[2, 3],完美符合预期。


如果把这行代码移到 if 条件外面会怎样?

假设代码写成这样(错误的写法):

for (int x : nums2) {if (hash[x]) {result.push_back(x);}hash[x] = false; // 错误:移到了if外面
}

同样用示例2分析:

  • •第一个 x=2满足条件,2被加入结果。然后 hash[2]被设为 false
  • •第二个 x=2不满足条件,被跳过。到这里还是正确的
  • 但是,当 x=8时,hash[8]原本是 false,但依然会执行 hash[8] = false;。这看起来没问题,但想象一下如果 nums2里有数字 1(它存在于 nums1中,hash[1]true),但这个 1出现在第一个 8之后: •在遇到 1之前,先遇到了 8hash[8]被设为 false(这没问题)。 •但 hash[1]仍然为 true,所以 1会被正确加入结果。 •问题在于,这种写法进行了不必要的操作,逻辑意图不清晰。我们的目的很明确:只有当某个元素被成功添加为交集时,才需要去标记它以防重复。对于根本不在 nums1里的元素(如 8),我们不需要也不应该在这个循环里去修改它的哈希状态。把操作放在 if 内部,使得代码的“目的”和“执行”高度一致。

结论

hash[x] = false;放在 if (hash[x])条件内部,实现了 “使用即失效” 的机制。这是一个非常巧妙且高效的去重方法,它确保了:

  1. 1.每个公共元素只被添加到结果中一次
  2. 2.代码逻辑清晰,只修改需要去重的元素的状态。

点击消除

在这里插入图片描述

代码如下:

#include <iostream>
#include <string>using namespace std;int main()
{string s,st;cin>>s;for(auto ch:s){if(st.size()&&st.back()==ch) st.pop_back();else st+=ch;}cout<<(st.size()==0?"0":st)<<endl;return 0;
}

1. for(auto ch : s)的含义

这是一种 C++ 中的范围 for 循环,也常被称为 foreach 循环

  • 作用:它用于按顺序遍历一个容器(比如这里的字符串 s)中的每一个元素。
  • 执行过程: 1.从字符串 s的第一个字符开始。 2.每次循环,将当前字符赋值给变量 ch。 3.执行循环体内的代码。 4.自动移动到下一个字符,直到遍历完整个字符串。

简单来说,for(auto ch : s)等价于下面这种传统的 for 循环:

for(int i = 0; i < s.size(); i++) {char ch = s[i]; // 取出字符串 s 中第 i 个位置的字符// ... 循环体 ...
}

但范围 for 循环的写法更简洁、更安全,不需要手动管理索引 i


2. 整个代码的逻辑讲解

这段代码是实现“点击消除”问题的另一种经典且高效的方法。它没有使用标准的 stack库,而是直接用字符串 st来模拟栈的行为,非常巧妙。

#include <iostream>
#include <string>
using namespace std;int main() {string s, st; // s: 输入字符串, st: 用来模拟栈的字符串cin >> s;// 核心循环:遍历输入字符串 s 中的每一个字符 chfor(auto ch : s) {// 条件1: st.size() => 判断"栈"是否非空// 条件2: st.back() == ch => 判断"栈"顶元素(即st的最后一个字符)是否与当前字符ch相同if(st.size() && st.back() == ch) {// 如果相同,则发生消除:将"栈"顶字符弹出st.pop_back();} else {// 如果不相同(或栈为空),则将当前字符压入"栈"顶st += ch;}}// 输出结果:如果模拟栈st为空,输出"0",否则输出栈中剩余字符串cout << (st.size() == 0 ? "0" : st) << endl;return 0;
}
如何用字符串 st模拟栈?
  • st的末尾(尾部)被视为栈顶
  • 入栈操作 (st += ch):向字符串末尾添加一个字符,相当于将字符压入栈顶。
  • 出栈操作 (st.pop_back()):移除字符串的最后一个字符,相当于从栈顶弹出一个字符。
  • 查看栈顶 (st.back()):获取字符串的最后一个字符,相当于查看栈顶元素。
  • 判断栈空 (st.size()):检查字符串长度是否为0,相当于判断栈是否为空。

3. 举例说明

我们用一个例子来模拟,比如输入是 abbc

当前字符 ch条件判断 (st非空且栈顶==ch?)操作模拟栈 st的变化
a初始st为空 -> 条件不成立执行 elsest += 'a'st = "a"
bst非空,栈顶 'a'!= 'b'-> 条件不成立执行 elsest += 'b'st = "ab"
bst非空,栈顶 'b'== 'b'-> 条件成立执行 ifst.pop_back()st = "a"(消除了两个b)
cst非空,栈顶 'a'!= 'c'-> 条件不成立执行 elsest += 'c'st = "ac"

循环结束,st不为空,输出 "ac"


总结

  • for(auto ch : s):是一种简洁的循环,用于遍历字符串 s中的每个字符。
  • 代码核心:使用字符串 st的末尾来模拟栈的后进先出特性,高效地解决了相邻字符消除的问题。
  • 优点:这种方法比使用标准库的 stack更节省内存,因为最后可以直接输出字符串 st,而无需像栈那样需要额外步骤来反转顺序。

st非空,栈顶 'a'!= 'c'-> 条件不成立 | 执行 elsest += 'c' | st = "ac" |

循环结束,st不为空,输出 "ac"


总结

  • for(auto ch : s):是一种简洁的循环,用于遍历字符串 s中的每个字符。
  • 代码核心:使用字符串 st的末尾来模拟栈的后进先出特性,高效地解决了相邻字符消除的问题。
  • 优点:这种方法比使用标准库的 stack更节省内存,因为最后可以直接输出字符串 st,而无需像栈那样需要额外步骤来反转顺序。

这种解法非常优雅和高效!

http://www.dtcms.com/a/593515.html

相关文章:

  • 基于PLC的多级传送带控制与改造
  • 网站建设案例知名 乐云践新广州市专业网站设计
  • 数字货币众筹网站开发创意设计公司官网
  • requst payload和query string parameters
  • Web网页之前端三剑客汇总篇(基础版)
  • 【AI学习-comfyUI学习-简易加载器抠图工作流(替换抠图节点版)-各个部分学习-第七节】
  • Linux中自定义服务开机自启nginx
  • 【Linux】snakemake应用之扩增子分析流程
  • 可以做哪些网站有哪些内容给别人做的网站要复杂做安全扫描
  • vue中回显word、Excel、txt、markdown文件
  • [吾爱大神原创] 自用 图片叠加 批量图片转PDF工具 [牛马工具]
  • 微信小程序开发案例 | 幸运抽签小程序(上)
  • GEAR:一种高效的 KV Cache 压缩方法,用于几乎无损的大语言模型生成式推理
  • 西樵网站建设公司wordpress 宠物
  • Bootstrap5 表格深度解析
  • abuild 命令行工程编译
  • python自动化005:app自动化入门环境搭建
  • 云南品牌网站开发番禺建设网站开发
  • HarmonyOS:线性布局(Row/Column)
  • 鸿蒙Next学习解析之针对PC2in1设备的窗口管理新增支持主窗的尺寸记忆功能
  • 【大数据技术02】统计学和模型
  • Python数据挖掘之回归
  • 数据管理技术发展的3个阶段
  • 进网站后台显示空白购买东西网站怎么做
  • 做网站的公司都有哪些模板制作方法
  • .NET线程池ThreadPool.QueueUserWorkItem
  • Python爬虫进阶:面向对象设计与反爬策略实战
  • 河北省建设厅网站站长万网主体新增网站备案需要是滴么
  • windows 11 系统 nvm安装详细教程 (踩坑分享)
  • VMMap 学习笔记(8.3):VMMap 窗口全解析——内存类型、指标含义、颜色视图怎么读