题解 | #坐标移动#

坐标移动

http://www.nowcoder.com/practice/119bcca3befb405fbe58abe9c532eb29

题目的主要信息:

  • 开发一个坐标计算工具, A表示向左移动,D表示向右移动,W表示向上移动,S表示向下移动
  • 从(0,0)点开始移动,从输入字符串里面读取一些坐标,并输出最终结果
  • 输入的合法坐标为A(或者D或者W或者S) + 数字(两位以内),坐标之间以;间隔
  • 非法坐标不操作

方法一:模拟

具体做法:

我们可以遍历输入的字符串,以分号为界限,利用substr函数分割成较小的坐标,放入数组中。然后我们设置坐标为(0,0)(0,0)(0,0),遍历字符串数组,对于每一个坐标首先检查其是否是空串或者长度是否在1到2之间,否则都是非法坐标,可以忽略。然后我们检查开头字母是否是ASDW中的一个,否则还是非法坐标。最后我们检查出去首字符的其他字符是否全是数字,如果出现了其他字符还是非法坐标,需要忽略。

对于合法坐标,我们遍历字符串后两位(有的只有1位),将字符转化成数字,然后利用switch选择ASDW相应的字母,对不同的坐标加减上面计算的数字。全部遍历完数组以后就可以输出了。

alt

#include<iostream>
#include<string>
#include<vector>
using namespace std;

int main(){
    string s;
    while(cin >> s){
        int x = 0;
        int y = 0;
        vector<string> everystr;
        for(int i = 0; i < s.length(); i++){
            int j = i;
            while(j < s.length() && s[j] != ';') //以分号为界限
                j++;
            everystr.push_back(s.substr(i, j - i)); //截取分号之间的部分加入数组
            i = j;
        }
        for(int i = 0; i < everystr.size(); i++){ //遍历字符串数组
            if(everystr[i].empty() || everystr[i].size() > 3 || everystr[i].size() < 2) //空串或者长度大于3或者小于2,忽略
                continue;
            //开头不为这四个字母也不合法,忽略
            if(everystr[i][0] != 'A' && everystr[i][0] != 'D' && everystr[i][0] != 'S' && everystr[i][0] != 'W')
                continue;
            bool flag = false;
            for(int j = 1; j < everystr[i].length(); j++) //查看方向后面除了数字还有无其他字符
                if(!(everystr[i][j] >= '0' && everystr[i][j] <= '9')){
                    flag = true;
                    break;
                }
            if(flag) //有其他字符,不合法
                continue;
            int dis = 0; //移动距离
            for(int j = 1; j < everystr[i].length(); j++)
                dis = 10 * dis + everystr[i][j] - '0'; //获取数字
            switch(everystr[i][0]){ //根据移动方向加减相应坐标
                case 'A': x -= dis; break;
                case 'D': x += dis; break;
                case 'W': y += dis; break;
                case 'S': y -= dis; break;
            }
        }
        cout << x << "," << y << endl;
    }
    return 0;
}

复杂度分析:

  • 时间复杂度:O(n)O(n)O(n)nnn为输入的字符串长度,不管是分割阶段还是计算阶段循环次数都不会超过最开始的字符串长度
  • 空间复杂度:O(n)O(n)O(n),最坏情况下,字符串数组vector最长为nnn

方法二:正则表达式

具体做法:

上述方法一有两个改进的地方,首先我们可以利用getline函数在输入的时候就以分号为界限,每次输入刚好是一个坐标,就不用再分割,用数组保存了。

然后就是利用正则表达式匹配来识别是否是合法字符:合法字符就是ASDW中一个字母后面接上1位或者2位数字,正则表达式为"[ADWS]\d{1,2}$"。我们对于上面得到的每个坐标进行正则匹配,如果不合法就忽略,如果合法就像方法一一样计算距离然后利用switch对每种情况单独计算。

#include<iostream>
#include<string>
#include<regex>
using namespace std;

int main(){
    string s;
    string patten = "[ADWS]\\d{1,2}$";
    regex r(patten);
    int x = 0;
    int y = 0;
    while(getline(cin, s, ';')){ //读取的时候就以分号分割坐标
        if(!regex_match(s, r)) //非法坐标
            continue;
       int dis = 0; //移动距离
       for(int i = 1; i < s.length(); i++)
           dis = 10 * dis + s[i] - '0'; //获取数字
       switch(s[0]){ //根据移动方向加减相应坐标
           case 'A': x -= dis; break;
           case 'D': x += dis; break;
           case 'W': y += dis; break;
           case 'S': y -= dis; break;
       }
    }
    cout << x << "," << y << endl;
    return 0;
}

复杂度分析:

  • 时间复杂度:O(n)O(n)O(n)nnn为输入的字符串长度,不管是正则表达式的匹配还是计算数字,总体上最多遍历字符串每个字符
  • 空间复杂度:O(1)O(1)O(1),正则表达式空间为常数
孤帆远影碧空尽 文章被收录于专栏

牛客网各类题单题解~

全部评论
点赞 回复 分享
发布于 2023-01-16 20:23 湖南

相关推荐

来,说点可能被同行“骂”的大实话。🙊当初接数字马力Offer时,朋友都说:“蚂蚁的“内包”公司?你想清楚啊!”但入职快一年后的今天,我反而对他有了不一样的看法!🔹&nbsp;是偏见?还是信息差!之前没入职之前外面都在说什么岗位低人一等这类。实际上:这种情况不可至否,不能保证每个团队都是其乐融融。但我在的部门以及我了解的周边同事都还是十分好相处的~和蚂蚁师兄师姐之间也经常开一些小玩笑。总之:身份是蚂蚁公司给的,地位是自己挣的(一个傲娇女孩的自述)。🔹&nbsp;待遇?玩的就是真实!试用期工资全额发!六点下班跑得快(早9晚6或者早10晚7,动态打卡),公积金顶格交。别听那些画饼的,到手的钱和下班的时间才是真的(都是牛马何必难为牛马)。🔹&nbsp;能不能学到技术?来了就“后悔”!我们拥有权限直通蚂蚁知识库,技术栈多到学不完。说“学不到东西”的人,来了可能后悔——后悔来晚了(哈哈哈哈,可以不学但是不能没有)!💥&nbsp;内推地址:https://app.mokahr.com/su/ueoyhg❗我的内推码:NTA6Nvs走我的内推,可以直达业务部门,面试流程更快速,进度可查!今天新放HC,之前挂过也能再战!秋招已经正式开始啦~机会就摆在这,敢不敢来试一试呢?(和我一样,做个勇敢的女孩)
下午吃泡馍:数字马力的薪资一般哇,5年经验的java/测试就给人一万出头,而且刚入职第三天就让人出差,而且是出半年
帮你内推|数字马力 校招
点赞 评论 收藏
分享
评论
6
3
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务