LeetCode——判斷子序列
阿新 • • 發佈:2020-08-09
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;
}