10.6-10.15力扣模拟刷题

补充知识:

模拟题的解题步骤

  1. 仔细阅读题目:
  • 理解每个规则和约束条件
  • 明确输入输出格式
  1. 设计数据结构
  • 选择合适的数据结构存储状态
  • 考虑如何高效访问和更新数据
  1. 实现核心逻辑
  • 按照问题描述逐步实现
  • 处理好状态转移
  1. 处理边界情况
  • 考虑各种极端情况
  • 添加必要的错误处理
  1. 测试验证
  • 用样例测试代码
  • 检查边界情况

【1】258. 各位相加

日期:10.6

1.题目链接:258. 各位相加 - 力扣(LeetCode)https://leetcode.cn/problems/add-digits/description/?envType=problem-list-v2&envId=simulation

2.类型:数学,数论,模拟

3.方法一:模拟(一次题解)

计算一个整数的各位相加的做法是,每次计算当前整数除以 10 的余数得到最低位数,将最低位数加到总和中,然后将当前整数除以 10。重复上述操作直到当前整数变成 0,此时的总和即为原整数各位相加的结果。

关键代码:

cpp 复制代码
       while(num>=10){
            int sum=0;
            while(num>0){
                sum+=num%10;
                num/=10;
            }
            num=sum;
        }

【2】412. Fizz Buzz

日期:10.7

1.题目链接:412. Fizz Buzz - 力扣(LeetCode)https://leetcode.cn/problems/fizz-buzz/description/?envType=problem-list-v2&envId=simulation

2.类型: 数学,字符串模拟

3.方法一:模拟(一次题解)

如果 i 是 3 的倍数,则将 "Fizz" 拼接到 answer[i];

如果 i 是 5 的倍数,则将 "Buzz" 拼接到 answer[i];

如果 answer[i] 为空,则 i 既不是 3 的倍数也不是 5 的倍数,将 i 拼接到 answer[i]。

关键代码:

cpp 复制代码
       vector<string> answer;
        for(int i=1;i<=n;i++){
            string curr;
            if(i%3==0){
                curr+= "Fizz";
            }
            if(i%5==0){
                curr+="Buzz";
            }
            if(curr.size()==0){
                curr+=to_string(i);
            }            
            answer.emplace_back(curr);
        }

【3】498. 对角线遍历

日期:10.8

1.题目链接:498. 对角线遍历 - 力扣(LeetCode)https://leetcode.cn/problems/diagonal-traverse/description/?envType=problem-list-v2&envId=simulation

2.类型: 矩阵,模拟

3.方法一:模拟(半解)

设矩阵的行数为 m, 矩阵的列数为 n:

设对角线从上到下的编号为 i∈[0,m+n−2]:

当 i 为偶数时,则第 i 条对角线的走向是从下往上遍历;

当 i 为奇数时,则第 i 条对角线的走向是从上往下遍历;

当第 i 条对角线从下往上遍历时,每次行索引减 1,列索引加 1,直到矩阵的边缘为止:

当 i<m 时,则此时对角线遍历的起点位置为 (i,0);
当 i≥m 时,则此时对角线遍历的起点位置为 (m−1,i−m+1);

当第 i 条对角线从上往下遍历时,每次行索引加 1,列索引减 1,直到矩阵的边缘为止:

当 i<n 时,则此时对角线遍历的起点位置为 (0,i);
当 i≥n 时,则此时对角线遍历的起点位置为 (i−n+1,n−1);

关键代码:

cpp 复制代码
        // 遍历所有对角线,共 m+n-1 条
        for(int i=0;i<m+n-1;i++){
            if(i%2){ 
                int x=i<n?0:i-n+1;
                int y=i<n?i:n-1;
                while(x<m&&y>=0){
                    res.emplace_back(mat[x][y]);
                    x++;  
                    y--;  
                }
            }else{      // 偶数索引对角线:从左下向右上遍历
                int x=i<m?i:m-1;
                int y=i<m?0:i-m+1;                
                // 沿对角线遍历
                while(x>=0&&y<n){
                    res.emplace_back(mat[x][y]);
                    x--;  
                    y++;  
                }
            }
        }

【4】537. 复数乘法

日期:10.9

1.题目链接:537. 复数乘法 - 力扣(LeetCode)https://leetcode.cn/problems/complex-number-multiplication/description/?envType=problem-list-v2&envId=simulation

2.类型: 数学,字符串,模拟

3.方法一:模拟(官方题解)

正则表达式:"\\+|i"

\\+:匹配加号字符 +(需要转义)

|:或操作符

i:匹配虚数单位 i

sregex_token_iterator 工作原理

sregex_token_iterator 是C++的正则表达式令牌迭代器:

第一个参数:字符串起始迭代器

第二个参数:字符串结束迭代器

第三个参数:正则表达式模式

第四个参数:-1 表示返回不匹配的部分(即分割后的令牌)

关键代码:

cpp 复制代码
        // 定义正则表达式,匹配 '+' 或 'i'
        regex re("\\+|i");         
        // 使用正则表达式分割第一个复数字符串
        vector<string> complex1(sregex_token_iterator(num1.begin(),num1.end(),re,-1), 
                               std::sregex_token_iterator());        
        // 使用正则表达式分割第二个复数字符串  
        vector<string> complex2(sregex_token_iterator(num2.begin(),num2.end(),re,-1), 
                               std::sregex_token_iterator());       
        // 提取实部和虚部并转换为整数
        int real1=stoi(complex1[0]);
        int imag1=stoi(complex1[1]);
        int real2=stoi(complex2[0]);
        int imag2=stoi(complex2[1]);      
        // 应用复数乘法公式并返回结果字符串
        return to_string(real1*real2-imag1*imag2)+"+"+ 
               to_string(real1*imag2+imag1*real2)+"i";

【5】415. 字符串相加

日期:10.10

1.题目链接:415. 字符串相加 - 力扣(LeetCode)https://leetcode.cn/problems/add-strings/description/?envType=problem-list-v2&envId=simulation

2.类型: 数学,字符串,模拟

3.方法一:模拟(半解)

定义两个指针 i 和 j 分别指向 num1​ 和 num2​的末尾,即最低位,同时定义一个变量 add 维护当前是否有进位,然后从末尾到开头逐位相加即可。统一在指针当前下标处于负数的时候返回 0,等价于对位数较短的数字进行了补零操作,这样就可以除去两个数字位数不同情况的处理。

关键代码:

cpp 复制代码
     while(i>=0||j>=0||add!=0){
            // 获取当前位的数字,如果已超出范围则用0填充
            int x=i>=0?num1[i]-'0':0;
            int y=j>=0?num2[j]-'0':0;           
            int result=x+y+add;            
            // 将当前位的结果添加到答案中
            ans.push_back('0'+result%10);          
            add=result/10;            
            i-=1;
            j-=1;
        }

【6】566. 重塑矩阵

日期:10.11

1.题目链接:566. 重塑矩阵 - 力扣(LeetCode)https://leetcode.cn/problems/reshape-the-matrix/description/?envType=problem-list-v2&envId=simulation

2.类型: 数组,模拟

3.方法一:二维数组的一维表示(一次题解)

使用数学映射将原矩阵的线性索引转换为新矩阵的二维坐标

通过除法运算确定行索引,取模运算确定列索引

保持元素的相对顺序不变

关键代码:

cpp 复制代码
        if(m*n!=r*c){
            return nums;  
        }
        vector<vector<int>> ans(r, vector<int>(c));      
        for(int x=0;x<m*n;++x){
            // 将原矩阵中的元素映射到新矩阵中
            ans[x/c][x%c]=nums[x/n][x%n];
        }

【7】592. 分数加减运算

日期:10.12

1.题目链接:592. 分数加减运算 - 力扣(LeetCode)https://leetcode.cn/problems/fraction-addition-and-subtraction/description/?envType=problem-list-v2&envId=simulation

2.类型: 数学,字符串,模拟

3.方法一:模拟(半解)

逐个解析表达式中的分数

使用通分法进行分数加法:a/b + c/d = (a*d + c*b) / (b*d)

最后化简分数,求分子分母的最大公约数

cpp 复制代码
        while(index<n){
            long long x1=0,sign=1;
            if(expression[index]=='-'||expression[index]=='+'){
                sign=expression[index]=='-' ? -1 : 1;
                index++;
            }
            while(index<n&&isdigit(expression[index])){
                x1=x1*10+expression[index]-'0';
                index++;
            }
            x1=sign*x1; 
            index++; 
            long long y1=0;
            while(index<n&&isdigit(expression[index])){
                y1=y1*10+expression[index]-'0';
                index++;
            }
            // 分数加法: x/y + x1/y1 = (x*y1 + x1*y) / (y*y1)
            x=x*y1+x1*y;
            y*= y1;
        }

【8】657. 机器人能否返回原点

日期:10.13

1.题目链接:657. 机器人能否返回原点 - 力扣(LeetCode)https://leetcode.cn/problems/robot-return-to-origin/description/?envType=problem-list-v2&envId=simulation

2.类型:字符串,模拟

3.方法一:模拟(一次题解)

起始点x=0,y=0。接下来我们遍历指令并更新机器人的坐标:

如果指令是 U,则令 y=y−1

如果指令是 D,则令 y=y+1

如果指令是 L,则令 x=x−1

如果指令是 R,则令 x=x+1

最后判断 (x,y) 是否为 (0,0) 即可。

关键代码:

cpp 复制代码
     for(const auto& move: moves){
            if(move=='U'){
                y--;
            }
            else if(move=='D'){
                y++;
            }
            else if(move=='L'){
                x--;
            }
            else if(move=='R'){
                x++;
            }
        }

【9】874. 模拟行走机器人

日期:10.14

1.题目链接:874. 模拟行走机器人 - 力扣(LeetCode)https://leetcode.cn/problems/walking-robot-simulation/description/?envType=problem-list-v2&envId=simulation

2.类型:数组,哈希表,模拟

3.方法一:哈希表(半解)

使用方向数组表示四个基本方向

用哈希集合高效存储和检查障碍物

模拟机器人的每一步移动,遇到障碍物时停止

在移动过程中持续更新最大距离

关键代码:

cpp 复制代码
         // 将障碍物坐标转换为唯一整数并存入哈希集合
        for(auto &obstacle:obstacles){
            mp.emplace(obstacle[0]*60001+obstacle[1]);
        }       
        int res=0;      
        for(int c : commands){
            if(c<0){
                d+=c==-1?1:-1; // -1右转90度,-2左转90度
                d%=4;                // 取模确保方向在0-3范围内
                if(d<0){
                    d+=4;            // 处理负数情况
                }
            }else{
                // 移动命令
                for(int i=0;i<c;i++){
                    // 检查下一个位置是否有障碍物
                    if(mp.count((px + dirs[d][0])*60001+py+dirs[d][1])){
                        break; // 遇到障碍物,停止移动
                    }
                    px+=dirs[d][0];
                    py+=dirs[d][1];
                    // 更新最大距离平方
                    res=max(res,px*px+py*py);
                }
            }
        }

【10】495. 提莫攻击

日期:10.15

1.题目链接:495. 提莫攻击 - 力扣(LeetCode)https://leetcode.cn/problems/teemo-attacking/description/?envType=problem-list-v2&envId=simulation

2.类型:数组,模拟

3.方法一:单词扫描(一次题解)

维护一个变量 expired 表示当前中毒效果的结束时间

对于每个攻击时间点:

如果攻击时没有中毒,添加完整的中毒时间

如果攻击时已经中毒,只添加新增加的中毒时间

累加所有有效的中毒时间

关键代码:

cpp 复制代码
      for(int i=0;i<timeSeries.size();++i){
            if(timeSeries[i]>=expired){
                // 攻击时没有中毒效果,添加完整的中毒时间
                ans+=duration;
            }else{
                // 攻击时已有中毒效果,添加重叠部分的时间
                ans+=timeSeries[i]+duration-expired;
            }
            // 更新中毒结束时间
            expired=timeSeries[i]+duration;
        }

【11】832. 翻转图像

日期:10.15

1.题目链接:832. 翻转图像 - 力扣(LeetCode)https://leetcode.cn/problems/flipping-an-image/description/?envType=problem-list-v2&envId=simulation

2.类型:数组,双指针,模拟

3.方法一:模拟优化 + 双指针(半解)

使用双指针技术同时完成水平翻转和像素反转

对于对称位置的两个像素:

如果它们相同,同时取反

如果它们不同,不需要操作(因为翻转后取反会相互抵消)

单独处理中间元素(当行长度为奇数时)

关键代码:

cpp 复制代码
       for(int i=0;i<n;i++){
            int left=0,right=n-1;  
            while(left<right){
                // 如果对称位置的像素值相同,同时取反
                if(image[i][left]==image[i][right]){
                    image[i][left]^=1;   // 使用异或操作取反
                    image[i][right]^=1;  // 0^1=1, 1^1=0
                }
                left++;
                right--;
            }            
            // 处理中间元素(当矩阵大小为奇数时)
            if(left==right){
                image[i][left]^=1;  // 中间元素取反
            }
        }

【12】1041. 困于环中的机器人

日期:10.15

1.题目链接:1041. 困于环中的机器人 - 力扣(LeetCode)https://leetcode.cn/problems/robot-bounded-in-circle/description/?envType=problem-list-v2&envId=simulation

2.类型:字符串,模拟

3.方法一:模拟(半解)

如果它的位置仍位于原点,那么不管它此时方向是什么,机器人都将永远无法离开。

如果它的位置不在原点,那么需要考虑此时机器人的方向:

如果机器人仍然朝北,那么机器人可以不会陷入循环。假设执行完一串指令后,机器人的位置是 (x,y) 且不为原点,方向仍然朝北,那么执行完第二串指令后,机器人的位置便成为 (2×x,2×y),会不停地往外部移动,不会陷入循环。

如果机器人朝南,那么执行第二串指令时,机器人的位移会与第一次相反,即第二次的位移是 (−x,−y),并且结束后会回到原来的方向。每两串指令之后,机器人都会回到原点,并且方向朝北,机器人会陷入循环。

如果机器人朝东,即右转了 90°。每执行一串指令,机器人都会右转 90°。那么第一次和第三次指令的方向是相反的,第二次和第四次指令的方向是相反的,位移之和也为 0,每四次指令之后,机器人都会回到原点,并且方向朝北,机器人会陷入循环。如果机器人朝西,也是一样的结果。

关键代码:

cpp 复制代码
       for(char instruction:instructions){
            if(instruction=='G'){
                // 前进:根据当前方向移动
                x+=direc[direcIndex][0];
                y+=direc[direcIndex][1];
            }else if(instruction=='L'){
                // 左转:逆时针旋转90度
                direcIndex+=3;  // 相当于 direcIndex - 1
                direcIndex%=4;  // 取模确保在0-3范围内
            }else{
                // 右转:顺时针旋转90度
                direcIndex++;
                direcIndex%=4;  // 取模确保在0-3范围内
            }
        }
相关推荐
徐子童4 小时前
算法---队列+宽搜
算法··队列·层序遍历
一念&4 小时前
每日一个C语言知识:C 数组
c语言·开发语言·算法
小年糕是糕手4 小时前
【数据结构】单链表“0”基础知识讲解 + 实战演练
c语言·开发语言·数据结构·c++·学习·算法·链表
咸鱼爱学习5 小时前
【题解】B2613【深基1.习5】打字速度
数据结构·c++·算法
一匹电信狗5 小时前
【C++】C++风格的类型转换
服务器·开发语言·c++·leetcode·小程序·stl·visual studio
测试19986 小时前
Jmeter是如何实现接口关联的?
自动化测试·软件测试·python·测试工具·jmeter·职场和发展·接口测试
CoderYanger6 小时前
前端基础——HTML练习项目:填写简历信息
前端·css·职场和发展·html
学学学无无止境6 小时前
力扣-上升的温度
leetcode
云青黛6 小时前
轮廓系数(一个异型簇的分类标准)
人工智能·算法·机器学习