首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >朋友给了一道大厂面试题,老梁一做发现不简单!

朋友给了一道大厂面试题,老梁一做发现不简单!

作者头像
TechFlow-承志
发布2022-09-22 14:30:59
发布2022-09-22 14:30:59
4260
举报
文章被收录于专栏:TechFlowTechFlow

作者 | 梁唐

出品 | 公众号:Coder梁(ID:Coder_LT)

大家好,我是梁唐。

最近看到了一道某大厂的面试题,很有意思。

题面很简单,只有一句话,叫做翻转句子中的单词顺序,例如原本是:how are you翻转之后变成you are how。

老梁一看,这还不简单?如果使用Python只需要一行:

代码语言:javascript
复制
def revert_word(sentence):
    return ' '.join(sentence.split(' ')[::-1])

这么操作了之后被朋友告知不能使用split函数,需要自己处理空格。

老梁想了一下,这也不难,我们用一个字符串维护当前的单词,遇到空格就把它添加到答案的开头:

代码语言:javascript
复制
string revert_word(string &input) {
    string word = "", ret = "";
    for (int i = 0; i < input.length(); i++) {
        if (input[i] == ' ') {
            ret = word + " " + ret;
            word = "";
            continue;
        }
        word = word + input[i];
    }
    return word + " " + ret;
}

但我们仔细想一下又会发现有一些问题,首先是这个word。我们每次读到新的字符之后都要拼接到末尾,这里其实有一个问题,在执行word = word + input[i]的时候,程序会先执行word + input[i]得到一个临时的字符串之后,再赋值给左侧的word,而不是在word本身进行修改。

我们都知道,复制是需要开销的,每次都是O(n)的操作。所以这样写的时间复杂度其实很大,接近O(n^2)

同样的问题还出现在更新ret的地方,所以表面上来看这个算法没问题,但仔细分析的话会发现它的复杂度是比我们预想的大的。

当我把我的分析告诉了朋友之后,他指出了另外一个问题,他说我们还用到了额外内存空间,面试官给的要求是除了时间复杂度控制在O(n) 之外,还需要将空间复杂度控制在O(1)

这就意味着我们不能再缓存单词,甚至不能存储拷贝,只能在原字符串上进行修改了。

老梁一开始的想法是维护两个指针分别指向头尾,拿到头尾的两个单词之后再进行交换。但这样有一个问题,就是当头尾的单词长度不一致的时候,没办法处理,如这种情况:

代码语言:javascript
复制
you xxxxx hello

我们要把hello和you两个单词交换位置,但交换之后会影响中间一系列字符的位置。显然在线性表当中移动元素是非常不明智的,自然这条路也就走不通了。

那有没有什么办法可以在O(n)的时间复杂度内做到这点呢?当然是有的,并且说白了很简单,甚至有点简单到出人意料,那就是翻转字符串。

你看原本是how are you的字符串在进行了翻转之后,会变成uoy era woh。不仅单词的顺序翻转了,并且每个单词当中的字母也翻转了。既然如此,那么我们只需要再将这些单词再翻转一遍即可。翻转单词显然是一个O(n) 的操作,并且也不需要额外的空间消耗。

除了算法本身,我们在写的时候还需要注意一下开发的规范,比如命名规范,传参的时候尽量传引用等等。

代码语言:javascript
复制
void swap_word(string &input, int l, int r) {
    while (l < r) {
        swap(input[l++], input[r--]);
    }
}

void revert_string(string &input) {
    reverse(input.begin(), input.end());
    int last = 0;
    for (int i = 0; i < input.length(); i++) {
        if (input[i] == ' ' && i > 0) {
            int l = last, r = i-1;
            swap_word(input, l, r);
            last = i+1;
        }
    }
    if (last < input.length()) {
        int l = last, r = input.length()-1;
        swap_word(input, l, r);
    }
}

这道题说难当然不算难,但说简单其实也没有那么简单,属于那种人人都能做,但未必都能想出最优解法的问题。非常能够考验一个工程师的功底,也的的确确配得上大厂面试题的称号。

后来老梁搜了一下,发现这题是剑指offer中的第58题,LeetCode中也有收录,感兴趣的小伙伴不妨亲自做做看~

新年在即,大家好好努力~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-01-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Coder梁 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档