最後一個單詞的長度和加一

沒錯,今天又是做簡單題的一天。

給定一個僅包含大小寫字母和空格 ' ' 的字符串,返回其最後一個單詞的長度。如果不存在最後一個單詞,請返回 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),高下立判。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章