最后一个单词的长度和加一

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/HermitSun/article/details/102755111

没错,今天又是做简单题的一天。

给定一个仅包含大小写字母和空格 ' ' 的字符串,返回其最后一个单词的长度。如果不存在最后一个单词,请返回 0。

看到这个题目,我的第一反应是双指针,快指针指向数组最后一个的时候,减掉停在最后一个' '上的慢指针,就能得到长度了。但是想想觉得用指针还不如直接计数来得实在,而且这样做存在一个问题,如果是类似于" a "这种的字符串,就需要保存之前的状态,所以还需要额外的空间来存储之前的状态,类似于dp。于是出来了这么一个丑陋的解法:

int lengthOfLastWord(string s)
{
    auto length = s.length();
    int count = 0;
    vector<int> vec;
    for (auto i = 0; i < length; ++i)
    {
        if (s[i] != ' ')
        {
            ++count;
        }
        else
        {
            vec.push_back(count);
            count = 0;
        }
    }
    vec.push_back(count);
    auto n = vec.size();
    int res = vec[n - 1];
    if (res)
    {
        return res;
    }
    else
    {
        for (int i = n - 1; i >= 0; --i)
        {
            if (vec[i])
            {
                return vec[i];
            }
        }
        return 0;
    }
}

估计是因为测试数据不大,结果居然还可以。但是我注意到了一件事,为什么非得正着数而不倒着数……明明倒着数效果更好,找第一个肯定比找最后一个简单。

同时,我还意识到,之前导致存储状态的罪魁祸首就是两边的空格,把空格去掉不就好了……所以又加了一个trim的函数。因为倒着数,所以去掉右边的空格就可以了。当然,trim不是我写的:

// trim from end (in place)
static inline void rtrim(std::string &s)
{
    s.erase(std::find_if(s.rbegin(), s.rend(),
                         std::not1(std::ptr_fun<int, int>(std::isspace)))
                .base(),
            s.end());
}

int lengthOfLastWord(string s)
{
    rtrim(s);
    int start = s.length() - 1;
    int i = start;
    for (; i >= 0; --i)
    {
        if (s[i] == ' ')
        {
            break;
        }
    }
    return start - i;
}

这样明显好一点。

至于加一这个题目,本来不想做的,但是看到和之前写的NASM的思路很像,忍不住就随手写了一下。主要就是三种情况吧,第一种不进位,第二种非最高位的进位,第三种是最高位的进位(比如999 + 1 = 1000)。思路很简单,模拟一个加法器就行了:

vector<int> plusOne(vector<int> &digits)
{
    int length = digits.size();
    bool carry = true;
    for (int i = length - 1; i >= 0; --i)
    {
        if (carry)
        {
            ++digits[i];
            carry = false;
        }
        if (digits[i] >= 10)
        {
            digits[i] -= 10;
            carry = true;
        }
        else
        {
            break;
        }
    }
    if (carry)
    {
        // 这里确实比使用insert要好
        digits[0] = 1;
        digits.push_back(0);
    }
    return digits;
}

但是有一点很有意思,我在处理最高位进位的时候使用了vector的insert方法。我们知道,vector在处理非尾部的insert的时候是很无力的。但是我看到某位dalao的解法里是这样写的:

digits[0] = 1;
digits.push_back(0);

在这个场景下,可以说是神来之笔了。在最后加一个0,然后把第一位改成1,和在最前面加一个1的效果是相同的,但是减小了开销(少了一个移动元素的过程)。这个写法的复杂度是O(1),而用insert的复杂度是O(m),高下立判。

猜你喜欢

转载自blog.csdn.net/HermitSun/article/details/102755111