我爱学算法之—— 模拟(上)

一、替换所有的问号

题目解析

替换所有的问号,给定一个字符串s(其中仅包含?和小写字母);我们要将s中所有的?替换成小写字母,并且还要保证最终的字符串中,不包含连续重复的字符(相邻的字符都不相同

算法思路

对于这道题,总体来说还是非常简单的;只需要按照题目要求遍历s,在遍历到?时将其替换成小写字母(与前一个字符和后一个字符都不相同)。

注意:

当第一个字符为?时,是不存在前一个字符的,只需要保证和后一个字母不相同即可;

当最后一个字符为?时,是不存在后一个字符的,只需要保证和前一个字符不相同即可。

代码实现

cpp 复制代码
class Solution {
public:
    string modifyString(string s) {
        int n = s.size();
        for (int i = 0; i < n; i++) {
            if (s[i] == '?') {
                for (char ch = 'a'; ch <= 'z'; ch++) {
                    if ((i == 0 || ch != s[i - 1]) &&
                        (i == n - 1 || ch != s[i + 1])) {
                        s[i] = ch;
                    }
                }
            }
        }
        return s;
    }
};

二、提莫攻击

题目解析

题目:提莫每次攻击会使艾希中毒duration秒,如果提莫攻击艾希时,艾希处于中毒状态,则时间会重置(不会叠加)。

先给定一个非递减的数组timeSeries,表示提莫攻击艾希的时间(提莫会在timeSeries[i]秒时攻击艾希)。

这道题目要求我们计算出,艾希处于中毒状态的总时间(秒)。

算法思路

对于这道题,思路也是非常简单,按照题目要求遍历timeSeries数组,统计艾希处于中毒状态的时间即可。

通过读题,我们会发现,提莫的最后一次攻击一定会导致艾希处于中毒状态duration秒;

而其他每一次攻击,导致艾希进入中毒状态的时间都和前一次攻击有关。

提莫第i+1次攻击攻击艾希时,无非就只有三种情况:

  • 当前艾希处于中毒状态:重置中毒时间,第i次攻击导致艾希处于中毒状态时间 timeSeries[i+1] - timeSeries[i]
  • 艾希刚好中毒状态解除:艾希进入中毒状态,第i次攻击导致艾希处于中毒状态时间 durationtimeSeries[i+] - timeSeries[i]
  • 艾希没有处于中毒状态:艾希进入中毒状态,第i次攻击导致艾希处于中毒状态时间 duration

所以,提莫第i次攻击,导致艾希的中毒时间:time = min(duration,timeSeries[i+1] - timeSeries[i]

所以,只需遍历[0 , n-2]次攻击,算出艾希中毒的时间再加上duration(第n-1次攻击必定导致艾希中毒duration秒)。

代码实现

cpp 复制代码
class Solution {
public:
    int findPoisonedDuration(vector<int>& timeSeries, int duration) {
        int ret = 0;
        int n = timeSeries.size();
        for (int i = 0; i < n - 1; i++) {
            int x = timeSeries[i + 1] - timeSeries[i];
            ret += min(duration, x);
        }
        ret += duration;
        return ret;
    }
};

三、Z 字形变换

题目解析

这道题,给定一个字符串s,这里要将字符串s从上往下,从左往右进行N字形排列;然后再从左往右逐行读取,产生一个新的字符串然后返回。

算法思路

对于这道题,思路就很清楚了:模拟整个过程

思路一:

排列N字形:

将字符串s排列成N字形,这里可以使用一个二维数组,将字符串s排列成如上图所示N字形,再遍历整个数组,形成结果字符串。


但是,这样做时间复杂度和空间复杂度都是O(n * numRows);并且遍历的过程中填写这个二维数组也是非常的麻烦。

这里,我们就可以使用C++中的string进行小小的空间和时间的优化。

优化一 :在填写二维数组的过程中,只需要关注要将字符放在哪一行中(哪一个字符串中)。

优化二 :在形成最终结果字符串时,只需要将字符串按行拼接在一起即可(字符串中不存在空格)。

思路二:

思路二也就是对模拟思路的一个优化:

在模拟过程中,直接将字符放到指定位置可能看不出来,这里使用下标代替字符:


可以发现,第一行的字符下标呈现出一个等差数列,公差为6(也就是这两列中,下面所有行的字符总数)

而最后一行的字符下标,也呈现出一个等差数列,公差为6

而中间的每一行,大眼一看,不是等差数列啊;仔细观察我们可以发现:中间的每一行,可以看成两个等差数列;其中一个数列首项为x,另一个数列首项就为6-x(也就是d - x

公差:显而易见,公差d = 2n - 2


所以,我们只需要先遍历第一行、再遍历中间的每一行、最后遍历最后一行(将每一行下标对应的字符,拼接成一个字符串返回即可)。

遍历的过程中,注意不要越界。

特殊情况:如果numRows等于1,此时计算出公差为0,并且numRows等于1时,无需转换,s就是最终结果。

这里就特殊处理,如果numRows等于1,就直接返回s

代码实现

思路一:

cpp 复制代码
class Solution {
public:
    string convert(string s, int numRows) {
        if (numRows == 1)
            return s;
        int i = 0;
        int flag = 0; // flag 0 -> i++  1 -> i--
        vector<string> vs(numRows, string());
        for (auto& e : s) {
            if (i == 0)
                flag = 0;
            else if (i == numRows - 1)
                flag = 1;
            vs[i] += e;
            if (flag == 0)
                i++;
            else
                i--;
        }
        string ret;
        for (auto& e : vs) {
            ret += e;
        }
        return ret;
    }
};

思路二:

cpp 复制代码
class Solution {
public:
    string convert(string s, int numRows) {
        if (numRows == 1)
            return s;
        int d = 2 * numRows - 2;
        int n = s.size();
        string ret;
        // 第一行
        for (int i = 0; i < n; i += d)
            ret.push_back(s[i]);
        // 中间行
        for (int k = 1; k < numRows - 1; k++) {
            for (int i = k, j = d - k; i < n || j < n; i += d, j += d) {
                if (i < n)
                    ret.push_back(s[i]);
                if (j < n)
                    ret.push_back(s[j]);
            }
        }
        // 最后一行
        for (int i = numRows - 1; i < n; i += d)
            ret.push_back(s[i]);
        return ret;
    }
};

本篇文章到这里就结束了,感谢支持

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws

相关推荐
Keying,,,,2 小时前
秋招算法记录 | 排序算法整理 | 直接选择、直接插入、冒泡、快排、希尔排序
数据结构·python·算法·排序算法
静若繁花_jingjing2 小时前
牛客算法题_二叉树
算法
仰泳的熊猫3 小时前
LeetCode:496. 下一个更大元素 I
数据结构·c++·算法·leetcode
bkspiderx3 小时前
C++设计模式之行为型模式:职责链模式(Chain of Responsibility)
c++·设计模式·责任链模式
勇闯逆流河3 小时前
【C++】AVL详解
开发语言·c++
未知陨落3 小时前
LeetCode:78.跳跃游戏
算法·leetcode
Wenhao.4 小时前
LeetCode-Hot100 最小栈实现
算法·leetcode
长安——归故李4 小时前
【PLC程序学习】
java·c语言·javascript·c++·python·学习·php
闲人编程4 小时前
会议安排问题之贪心算法
python·算法·ios·贪心算法·会议问题·算法改进·codecapsule