LeetCode392.Is Subsequence題解

1. 題目描述

Given a string s and a string t, check if s is subsequence of t. You may assume that there is only lower case English letters in both s and t. t is potentially a very long (length ~= 500,000) string, and s is a short string (<=100). A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, “ace” is a subsequence of “abcde” while “aec” is not).

2. 樣例

Example 1:
s = "abc", t = "ahbgdc"
Return true.

Example 2:
s = "axc", t = "ahbgdc"
Return false.

3. 分析

題目的意思是給了兩個字符串,需要我們判斷第一個字符串是否可以成爲第二個字符串的字串:成爲條件是第一個字符串按照順序出現在第二個字符串裏面,可以不連續。
拿到問題,最容易想到的思路就是O(n^2)的兩層循環:外層爲第一個字符串,裏層爲第二個字符串逐一遍歷匹配。可謂是暴力破解,然而我看了一眼題目的設置:第一個字符串長度約爲100以內,第二個長度則是500000,暴力破解沒得玩,於是另闢蹊徑。

3.1. 左右掃描法

於是我想到了模仿快速排序的思路:從左至右開始掃射,兩個字符串同時掃射。這樣就只需要一層循環遍歷即可,循環的條件是第二個字符串t的左邊下標小等於右邊下標以及外層循環的左右下標不超過邊界。當字符串s的左右兩邊下標相遇並驗證完中間的字符,則可以提前退出循環。用圖表示如下:
這裏寫圖片描述
根據這種思想,寫成的代碼時間複雜度應該是log(n),通過了測試,得到了如下結果:
這裏寫圖片描述
看來效果還不是特別理想。

3.2. 同向掃描

後來發現根本用不着兩邊同時掃,從一個方向掃描遍歷即可!!時間複雜度是O(n),然後速度比第一種方法要好一些。不過我這裏比較奇怪的是理論來說,兩邊同時掃描應該時間更爲節省纔對,但是結果的確不如單向掃描的結果。我猜測原因是我寫的左右掃描的代碼比較冗餘,有些重複的計算可以簡化,希望有興趣的朋友在評論區討論。
這裏寫圖片描述

4. 源碼

4.1. 左右掃描

class Solution {
public:
    bool isSubsequence(string s, string t) {
        if (s.size() > t.size()) {
           return false;
        }
        int counter_s = 0;
        int left_s = 0, left_t = 0, right_s = s.size()-1, right_t = t.size()-1;

        while(left_t <= right_t && left_t <= (int)t.size()-1 && right_t >= 0) {
            if (s[left_s] == t[left_t]) {
                if (left_s == right_s) {
                    counter_s++;
                    break;
                }
                else {
                    left_s++;
                    left_t++;
                    counter_s++;
                }
            }
            else {
                left_t++;
            }

            if (s[right_s] == t[right_t]) {
                if (left_s == right_s) {
                    counter_s++;
                    break;
                }
                else {
                    right_s--;
                    right_t--;
                    counter_s++;
                }
            }
            else {
                right_t--;
            }
        }
        if (counter_s == (int)s.size()) {
            return true;
        }
        return false;
    }
};

4.2. 單向掃描

class Solution {
public:
    bool isSubsequence(string s, string t) {
        int s_length = s.size(), t_length = t.size();
        int index_s = 0;
        for (int i = 0; i < t_length && index_s < s_length; i++) {
            if(s[index_s] == t[i]) {
                index_s++;
            }
        }
        if (index_s == s_length) {
            return true;
        }
        return false;
    }
};

5. 心得

算法的思路很重要,然而具體實現的方法也很重要,有些情況下優秀的思路但是複雜的實現不僅不會降低工作強度反而會影響效率。

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