算法:還有比二分查找更快的算法,判斷是否是子字符串Is Subsequence

題目

392. Is Subsequence
Given a string s and a string t, check if s is subsequence of t.

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).

Follow up:

If there are lots of incoming S, say S1, S2, … , Sk where k >= 1B, and you want to check one by one to see if T has its subsequence. In this scenario, how would you change your code?

Credits:

Special thanks to @pbrother for adding this problem and creating all test cases.

Example 1:

Input: s = "abc", t = "ahbgdc"
Output: true

Example 2:

Input: s = "axc", t = "ahbgdc"
Output: false

Constraints:

  1. 0 <= s.length <= 100
  2. 0 <= t.length <= 10^4
  3. Both strings consists only of lowercase characters.

來源:力扣(LeetCode)

鏈接:https://leetcode-cn.com/problems/is-subsequence

著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

解法一

解決思路:筆者看這道題是二分查找的類型題,很自然就從二分查找,用左右兩個座標同時來匹配。短字符串s的左座標爲sleft, 右座標爲sright; 長字符串t的左座標爲tleft, 右座標爲tright.

檢查邊界問題,比如短字符爲空s == null || s.length() == 0, 則直接返回true;如果長字符爲空t == null || t.length() == 0,則直接返回false;

循環遍歷條件爲長字符串tleft <= tright , 在循環結束前tleft++; tright–;。

如果短字符串的左邊字符等於長字符串的左邊字符串,則sleft++;;如果短字符串的右邊字符等於長字符串的右邊字符串,則sright–;。

在結束前判斷短字符串的sleft > sright,則返回true。 注意:筆者這裏踩過坑,如果放到最前面判斷,有可能,長字符串也結束了,導致結果還是false。

public boolean isSubsequence(String s, String t) {
    // check edge for s
    if (s == null || s.length() == 0) {
      return true;
    }
    // check edge for t
    if (t == null || t.length() == 0) {
      return false;
    }
    boolean result = false;
    int sleft = 0;
    int sright = s.length() - 1;
    int tleft = 0;
    int tright = t.length() - 1;
    while (tleft <= tright) {
      if (s.charAt(sleft) == t.charAt(tleft)) {
        sleft++;
      }
      if (s.charAt(sright) == t.charAt(tright)) {
        sright--;
      }
      
      if (sleft > sright) {
        return  true;
      }
      tleft++;
      tright--;
    }
    return result;
  }

解法二

筆者跑完以後,以爲速度會是最快了,看了以後只能超過87%的提交。看了一下評論,發現還有更優解。

解題思路如下:

遍歷短字符串的所有字符,比如遍歷到短字符的c,如果長字符集能從前一個找到的字符的位置加一(第一個字符的初始值爲-1),能找到當前字符c,則返回第一次找到該字符的位置,則替換index爲上一個找到的字符集;如果沒有找到當前字符c,則結果是-1,如果是-1,則直接返回false。時間複雜度只有最短字符的長度,最快的情況下,如果第一個字符都沒找到就直接退出。神來之筆。

public boolean isSubsequenceByIndexOfChar(String s, String t) {
    int index = -1;
    for (char c: s.toCharArray()) {
      index = t.indexOf(c, index + 1);
      if (index == -1) {
        return false;
      }
    }
    return true;
  }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章