1. 程式人生 > 實用技巧 >LeetCode——判斷子序列

LeetCode——判斷子序列

Q:給定字串 s 和 t ,判斷 s 是否為 t 的子序列。
你可以認為 s 和 t 中僅包含英文小寫字母。字串 t 可能會很長(長度 ~= 500,000),而 s 是個短字串(長度 <=100)。
字串的一個子序列是原始字串刪除一些(也可以不刪除)字元而不改變剩餘字元相對位置形成的新字串。(例如,"ace"是"abcde"的一個子序列,而"aec"不是)。

示例 1:
s = "abc", t = "ahbgdc"
返回 true.

示例 2:
s = "axc", t = "ahbgdc"
返回 false.

A:
雙指標

    public boolean isSubsequence(String s, String t) {
        if (s.length() == 0)
            return true;
        if (t.length() == 0 || t.length() < s.length())
            return false;
        int indexs = 0;
        int indext = 0;
        while (indexs < s.length() && indext < t.length()) {
            if (s.charAt(indexs) == t.charAt(indext)) {
                indexs++;
            }
            indext++;
        }
        return indexs == s.length();
    }

還有一個利用java本身的函式的,特別方便:java中String類有這樣一個方法public int indexOf(int ch, int fromIndex) ,他表示的是在字串中是否存在一個字元ch,並且是從字串的下標fromIndex開始查詢的。我們要做的是在t字串中查詢s中的每一個字元,如果沒查到,直接返回false。如果查到,就從t的下一個位置繼續開始查

    public boolean isSubsequence(String s, String t) {
        int index = -1;
        for (char c : s.toCharArray()) {
            //index表示上一次查詢的位置(第一次查詢的時候為-1),所以這裡要從t的下標(index+1)開始查詢
            index = t.indexOf(c, index + 1);
            //沒找到,返回false
            if (index == -1)
                return false;
        }
        return true;
    }

後續挑戰 :
如果有大量輸入的 S,稱作S1, S2, ... , Sk 其中 k >= 10億,你需要依次檢查它們是否為 T 的子序列。在這種情況下,你會怎樣改變程式碼?
引用:對後續挑戰的一些思考--如何快速判斷大量字串
我們前期多做一點工作,將長字串研究透徹,假如長字串的長度為 nn,建立一個 n * 26n∗26 大小的矩陣,表示每個位置上26個字元下一次出現的位置,對於要匹配的短字串,遍歷每一個字元,不斷地尋找該字元在長字串中的位置,然後將位置更新,尋找下一個字元,相當於在長字串上“跳躍”。如果下一個位置為 -1,表示長字串再沒有該字元了,返回 false 即可。

    public boolean isSubsequence(String s, String t) {

        //考慮到  對第一個字元的處理 ,在t 之前一個空字元
        t=' '+t;

        //對t長字串 做預處理
        int[][] dp = new int[t.length()][26];//儲存每一個位置上  a--z的下一個字元出現的位置
        for (char c = 'a'; c <= 'z'; c++) {//依次對每個字元作處理
            int nextPos = -1;//表示接下來不會在出現該字元

            for (int i = t.length() - 1; i >= 0; i--) {//從最後一位開始處理
                dp[i][c - 'a'] = nextPos;//dp[i][c-'a']  加上外層迴圈  就是對每一個位置的a---z字元的處理了
                if (t.charAt(i) == c) {//表示當前位置有該字元  那麼指向下一個該字元出現的位置就要被更新為i
                    nextPos = i;
                }
            }
        }

        //資料的利用 ,開始匹配
        int index=0;
        for (char c:s.toCharArray()){
            index=dp[index][c-'a'];//因為加了' ',所以之後在處理第一個字元的時候  如果是在第一行,就會去第一行,不影響之後字元的判斷
            if(index==-1){
                return false;
            }
        }
        return true;
    }