首页 > 其他分享 >随想录Day8|344. 反转字符串、541. 反转字符串Ⅱ、LCR 122. 路径加密、151. 反转字符串里的单词、LCR182. 动态口令

随想录Day8|344. 反转字符串、541. 反转字符串Ⅱ、LCR 122. 路径加密、151. 反转字符串里的单词、LCR182. 动态口令

时间:2023-09-28 13:22:10浏览次数:65  
标签:空格 ++ 反转 随想录 len 单词 fast 字符串

随想录Day8|344. 反转字符串、541. 反转字符串Ⅱ、LCR 122. 路径加密、151. 反转字符串里的单词、LCR182. 动态口令

 

题目越来越长了……

 

344. 反转字符串

文章&视频讲解

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

  • 1 <= s.length <= 105
  • s[i] 都是 ASCII 码表中的可打印字符

 

第一想法

(愣了很久没想法)原地修改?那就是两面包抄的两两交换,我似乎明白了,用局部变量每次存两个,就不会给数组开额外空间。

如果长度为len,每次交换s[i]s[len - 1 - i],需要确定i的变化范围。如果len是偶数比如4,则最后i需要在1,所以是i < 2;如果len是奇数比如5,则最后i需要在1,也是i < 2,综上应该是i < len / 2

 

用时12min~

void reverseString(vector<char> &s)
{
    int len = s.size();
    char left, right;
    for (int i = 0; i < len / 2; i++)
    {
        left = s[i];
        right = s[len - 1 - i];
        s[i] = right;
        s[len - 1 - i] = left;
    }
}

 

541. 反转字符串Ⅱ

文章&视频讲解

给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。

  • 如果剩余字符少于 k 个,则将剩余字符全部反转。
  • 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

提示:

  • 1 <= s.length <= 104
  • s 仅由小写英文组成
  • 1 <= k <= 104

 

第一想法

和上面的整体思路差不多,但是需要多注意一些边界条件的细节。用i来代表这次翻转的起始点,每次增加2k步,翻转(s.begin() + i, s.begin() + i + k)区间内的元素。

 

用时13min~

string reverseStr(string s, int k)
{
    int len = s.size();
    for (int i = 0; i < len; i += (2 * k))
    {
        if (i + k <= len)
            reverse(s.begin() + i, s.begin() + i + k);
        else
            reverse(s.begin() + i, s.end());
    }
    return s;
}

 

LCR 122. 路径加密

原本剑指offer 05. 替换空格,文章讲解也是对原题的。

文章讲解

假定一段路径记作字符串 path,其中以 "." 作为分隔符。现需将路径加密,加密方法为将 path 中的分隔符替换为空格 " ",请返回加密后的字符串。

0 <= path.length <= 10000

 

第一想法

直接扫描替换就好了……啊……最简单的一集?

好吧!原题是需要把空格替换成%20,所以涉及到空间分配!我是说呢……

用时3min~

string pathEncryption(string path)
{
    int len = path.length();
    for (int i = 0; i < len; i++)
    {
        if (path[i] == '.')
            path[i] = ' ';
    }
    return path;
}

 

151. 反转字符串里的单词

文章&视频讲解

给你一个字符串 s ,请你反转字符串中 单词 的顺序。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

  • 1 <= s.length <= 104
  • s 包含英文大小写字母、数字和空格 ' '
  • s至少存在一个 单词

 

第一想法

需要注意很多细节啊,先写着吧……首先就是多个空格的情况需要跳过余下的,然后每次以单词为单位翻转,是否需要事先统计单词个数?原地如何实现,如果首尾单词不一样长,中间的部分如何放置?

 

看完随想录题解的想法

没错我偷看思路去了,不过我只看了最核心的那一句!先移除多余空格,再翻转整个数组,最后翻转每个单词。

移除多余空格的时候如果使用erase(),则本身操作的复杂度\(O(n)\)和字符串长度\(n\),会导致最终整体复杂度\(O(n^2)\),所以采用双指针法,一个指向原字符串正在处理的位置,一个指向新字符串要写入的位置,这也是原地的,因为新字符串的长度小于等于原来的,所以相当于把后面的内容搬运到前面来,原地也不会造成数据之间的干扰。

在翻转单词的时候,读到这个单词后面的空格则翻转刚刚的单词,通过每遇到一个字母就wordlen++记录下来的就是刚刚这个单词的长度,比如字符串为hello world时候,第一次遇到空格时wordlen = 5,此时也有i = 5,翻转范围应该是[0, 5),所以最终应该是reverse(s.begin() + i - wordlen, s.begin() + i)

 

初代目答案

耗时73min~

string reverseWords(string s)
{
    // 先除去多余的空格
    // fast指向原字符串正在处理的,slow指向搬运目的地
    int fast = 0, slow = 0;
    // 处理多个连续空格,遇到第一个时设为true,之后看见true则跳过剩下空格
    bool spaceflag = false;
    int len = s.length();

    // 去掉前导空格
    while (s[fast] == ' ')
        fast++;

    while (fast < len)
    {
        if (s[fast] == ' ')
        {
            // 如果flag是true,则跳过
            if (spaceflag)
            {
                fast++;
                continue;
            }
            else // 可能是正常空格,可能是一串空格的第一个
            {
                spaceflag = true;
                s[slow++] = ' '; // 也就是s[slow] = s[fast]; slow++;
                fast++;
            }
        }
        else // 正常字符,搬运,并且把flag重置
        {
            s[slow++] = s[fast++];
            spaceflag = false;
        }
    }

    // 去掉尾随空格
    while (s[slow - 1] == ' ')
        slow--;
    s.resize(slow);

    // 把整个字符串都翻转
    reverse(s.begin(), s.end());

    // 原地翻转每个单词
    int i = 0;
    int wordlen = 0;
    while (i < slow) // 注意slow才是新的len
    {
        if (s[i] == ' ') // 翻转上一个单词并重置wordlen
        {
            reverse(s.begin() + i - wordlen, s.begin() + i);
            wordlen = 0;
        }
        else
            wordlen++;
        i++;
    }
    // 翻转最后一个单词
    reverse(s.end() - wordlen, s.end());

    return s;
}

 

学习题解更简洁的答案

可以把第一部分(上面10~41行)替换为这样。

for (; fast < len; fast++)
{
    if (s[fast] != ' ') // 有效字母
    {
        // 不是第一个单词,则前面加空格
        if (slow != 0)
            s[slow++] = ' ';
        // 然后一次处理完一个单词直到遇到空格
        while (fast < len && s[fast] != ' ')
            s[slow++] = s[fast++];
    }
}
s.resize(slow);

 

LCR182. 动态口令

文章讲解

某公司门禁密码使用动态口令技术。初始密码为字符串 password,密码更新均遵循以下步骤:

  • 设定一个正整数目标值 target
  • passwordtarget 个字符按原顺序移动至字符串末尾

请返回更新后的密码字符串。

  • 1 <= target < password.length <= 10000

 

第一想法

先把前target存起来,把后面的往前移?但是如果最坏的情况,target = password.length - 1,则空间复杂度过高。

可以采取上一题那种局部反转+整体反转的思路!如果分别反转前target个和后半段,再整体反转字符串即可。

 

用时8min~

string dynamicPassword(string password, int target)
{
    reverse(password.begin(), password.begin() + target);
    reverse(password.begin() + target, password.end());
    reverse(password.begin(), password.end());
    return password;
}

主要还是这个思路有点难想到,实现起来只需要三行!

 

碎碎念

这是第一次拖到了第二天,昨天有活动,回去之后只想睡大觉!

马上就开始做今天的啦!而且我还有好多作业没写,估计之后还要再发数字信号处理、张量学习、数据库、社会网络、深度学习、LLM相关论文的整理……额啊啊……就这情况你竟然还敢摸鱼……

标签:空格,++,反转,随想录,len,单词,fast,字符串
From: https://www.cnblogs.com/alouette/p/17735531.html

相关文章

  • ASP.NET截取字符串函数
    #region截取指定字数字符串///<summary>///格式化字符串,取字符串前strLength位,其他的用...代替.///计算字符串长度。汉字两个字节,字母一个字节///</summary>///<paramname="str">字符串</param>///<paramname=......
  • string字符串操作
    string字符串操作 usingSystem;usingSystem.Linq;usingUnityEngine;publicclassGuse:MonoBehaviour{voidStart(){stringstr="ASc_b16U2ja";string[]vari=str.Split('_');//根据单个字符切割Debug.Log(v......
  • ASP.NET截取字符串函数
    #region截取指定字数字符串///<summary>///格式化字符串,取字符串前strLength位,其他的用...代替.///计算字符串长度。汉字两个字节,字母一个字节///</summary>///<paramname="str">字符串</param>///<paramname="......
  • mssql中常用的字符串函数大集合
    1.绝对值SQL:selectabs(-1)valueO:selectabs(-1)valuefromdual2.取整(大)S:selectceiling(-1.001)valueO:selectceil(-1.001)valuefromdual3.取整(小)S:selectfloor(-1.001)valueO:selectfloor(-1.001)valuefromdual4.取整(截取)S:selectcast(-1.002asint)v......
  • 定位元素 (字符串)和方法 做分离
    #导包fromseleniumimportwebdriverfromselenium.webdriver.common.byimportByfromselenium.webdriver.support.uiimportWebDriverWaitfromselenium.webdriver.supportimportexpected_conditionsasEC#定义driverdriver=webdriver.Chrome()#打开浏览器dr......
  • 无字符串RCE
    来自:[CISCN2019初赛]LoveMath源码审计一打开就是源码<?phperror_reporting(0);//听说你很喜欢数学,不知道你是否爱它胜过爱flagif(!isset($_GET['c'])){show_source(__FILE__);}else{//例子c=20-1$content=$_GET['c'];if(strlen($content)>=......
  • 创建一个日期与字符串之间处理的工具
    packagecn.com.maple.utils;importorg.apache.logging.log4j.LogManager;importorg.apache.logging.log4j.Logger;importorg.joda.time.DateTime;importorg.joda.time.format.DateTimeFormat;importorg.joda.time.format.DateTimeFormatter;/***@authorLiDY*@desc......
  • Linux vi替换字符串
     1.基本的替换 :s/vivian/sky/替换当前行第一个vivian为sky :s/vivian/sky/g替换当前行所有vivian为sky :n,$s/vivian/sky/替换第n行开始到最后一行中每一行的第一个vivian为sky :n,$s/vivian/sky/g替换第n行开始到最后一行中每一行所有vivian为sky......
  • Redis系列 - Redis底层数据结构(简单动态字符串(SDS)、链表、字典、跳跃表、整数集合
    转自:https://blog.csdn.net/u011485472/article/details/109460490Redis系列-Redis底层数据结构(简单动态字符串(SDS)、链表、字典、跳跃表、整数集合、压缩列表)简单动态字符串(simpledynamicstring,SDS)链表字典跳跃表整数集合压缩列表RedisObject在介绍Redis底......
  • MYSQL 连接数据库过程中发生错误,检查服务器是否正常连接字符串是否正确,错误信息:未将对
    一:中文提示:连接数据库过程中发生错误,检查服务器是否正常连接字符串是否正确,错误信息:未将对象引用设置到对象的实例。DbType="MySql";ConfigId="".EnglishMessage:Connectionopenerror.未将对象引用设置到对象的实例。DbType="MySql";ConfigId="" 解决方法:在连接字......