Leetcode - Wildcard Matching

My code:

public class Solution {
    public boolean isMatch(String s, String p) {
        if (s == null || p == null) {
            return false;
        }
        
        int ss = 0;
        int pp = 0;
        int star = - 1;
        int match = -1;
        
        while (ss < s.length()) {
            if (pp < p.length() && p.charAt(pp) == '?') {
                ss++;
                pp++;
            }
            else if (pp < p.length() && p.charAt(pp) == s.charAt(ss)) {
                ss++;
                pp++;
            }
            else if (pp < p.length() && p.charAt(pp) == '*') {
                star = pp;
                match = ss;
                pp++;
            }
            else if (star != -1) {
                pp = star + 1;
                match++;
                ss = match;
            }
            else {
                return false;
            }
        }
        
        while (pp < p.length()) {
            if (p.charAt(pp) != '*') {
                return false;
            }
            pp++;
        }
        
        return true;
    }
}

這道題目是看了答案后寫出來的。
看了答案后感覺思路很清晰剪验,很簡潔肴焊。這才算是上乘的解法吧。

從頂層看功戚,他是按照 * 分成一個(gè)個(gè)塊娶眷。當(dāng)一個(gè)塊匹配完了,進(jìn)入下一個(gè)模塊啸臀。什么時(shí)候匹配完届宠? ---> 當(dāng)碰到下一個(gè) * 時(shí)。
雙指針。當(dāng)碰到正規(guī)字符或者 ? 時(shí)豌注,都是正常的往前移動(dòng)伤塌。
當(dāng)碰到 *時(shí),記錄下此刻的位置幌羞,已經(jīng) s 處的位置寸谜。然后用下一位和s原位置進(jìn)行匹配。
這是第一種情況属桦,即 * -> empty
然后雙指針移動(dòng)熊痴,然后突然又不匹配了。
于是 pp 再次回到 star + 1, ss 回到 match(此時(shí) match 本身 + 1)
此刻聂宾, * 表示一個(gè)字母果善。
然后雙指針繼續(xù)移動(dòng),失敗了系谐,再退回來巾陕。然后 * 表示兩個(gè)字母,繼續(xù)纪他。
直到鄙煤, ss 走到頭,或者 pp走到下一個(gè) * ,然后茶袒,這個(gè) * 的任務(wù)就完成了梯刚,我們通過了這層模塊的比較。

當(dāng) ss到頭時(shí)薪寓,判斷 pp 到頭是否都是 *, 如果不是亡资,就得返回 false
reference:
https://discuss.leetcode.com/topic/3040/linear-runtime-and-constant-space-solution

下面介紹 DP

My code:

public class Solution {
    public boolean isMatch(String s, String p) {
        if (s == null || p == null) {
            return false;
        }
        
        int row = s.length() + 1;
        int col = p.length() + 1;
        
        boolean[][] dp = new boolean[row][col];
        dp[0][0] = true;
        for (int i = 1; i < col; i++) {
            if (p.charAt(i - 1) == '*') {
                dp[0][i] = dp[0][i - 1];            
            }
        }

        for (int i = 1; i < row; i++) {
            for (int j = 1; j < col; j++) {
                if (p.charAt(j - 1) != '*') {
                    if (p.charAt(j - 1) == '?' || p.charAt(j - 1) == s.charAt(i - 1)) {
                        if (dp[i - 1][j - 1]) {
                            dp[i][j] = true;
                        }
                    }
                    else {
                        dp[i][j] = false;
                    }
                }
                else {
                    dp[i][j] = dp[i - 1][j] || dp[i][j - 1] || dp[i - 1][j - 1];
                }
            }
        }
        
        return dp[row - 1][col - 1];
    }
}

reference:
http://buttercola.blogspot.com/2014/10/leetcode-wildcard-matching.html

初始狀態(tài):
dp[s.length() + 1][p.length() + 1]
dp[i][j] 表示 s 中前i個(gè)字母 與 p 中前j個(gè)字母是否match
唯一需要認(rèn)真考慮的是 *
如果
p.charAt(j) != '*'
那么, 如果 dp[i - 1][j - 1] == true
并且
s.charAt(i) == p.charAt(j) or p.charAt(j) == '?'
那么向叉,dp[i][j] = true;

如果
p.charAt(j) == '*'
那么锥腻,
如果 dp[i - 1][j - 1] == true, 即,s的前i個(gè)字母與p的前j個(gè)字母match母谎,然后 * 用來表示 s.charAt(i - 1), 那么是可以match的

如果 dp[i][j - 1] == true, 即瘦黑, s的前i個(gè)字母與p的前 j - 1個(gè)字母match,然后用 * 來表示 empty, 那么也是可以match的奇唤。

如果 dp[i - 1][j] == true, 即供璧, s的前i - 1 個(gè)字母與p的前j個(gè)字母match,并且p的第j個(gè)字母是 冻记,那么睡毒,用一起把s.charAt(i - 1)也表示了,即冗栗, * 表示不止一個(gè)的字母演顾,那么也是可以match的供搀。

這就是遞推式。然后就可以DP了钠至。

好久沒做DP了葛虐。 這道題目很像 edit distance 等題目。現(xiàn)在開始做棉钧。

Anyway, Good luck, Richardo! -- 08/1

My code:
iteration

public class Solution {
    public boolean isMatch(String s, String p) {
        int ss = 0;
        int pp = 0;
        int star = -1;
        int match = -1;
        while (ss < s.length()) {
            if (pp < p.length() && (s.charAt(ss) == p.charAt(pp) || p.charAt(pp) == '?')) {
                ss++;
                pp++;
            }
            else if (pp < p.length() && p.charAt(pp) == '*') {
                star = pp;
                match = ss;
                pp++;
            }
            else if (star != -1) {
                pp = star + 1;
                match++;
                ss = match;
            }
            else {
                return false;
            }
        }
        
        for (int i = pp; i < p.length(); i++) {
            if (p.charAt(i) != '*') {
                return false;
            }
        }
        
        return true;
    }
}

DP:
My code:

public class Solution {
    public boolean isMatch(String s, String p) {
        if (p.length() == 0) {
            return s.length() == 0;
        }
        else if (p.length() == 1) {
            if (s.length() == 1 && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.')) {
                return true;
            }
            else {
                return false;
            }
        }
        else if (p.charAt(1) != '*') {
            if (s.length() == 0) {
                return false;
            }
            else if (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.') {
                return isMatch(s.substring(1), p.substring(1));
            }
            else {
                return false;
            }
        }
        else {
            if (isMatch(s, p.substring(2))) {
                return true;
            }
            while (s.length() > 0 && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.')) {
                 s = s.substring(1);
                if (isMatch(s, p.substring(2))) {
                    return true;
                }
            }
            return false;
        }
    }
}

看了下以前的答案屿脐,再寫了下。

Anyway, Good luck, Richardo! -- 09/16/2016

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末宪卿,一起剝皮案震驚了整個(gè)濱河市的诵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌佑钾,老刑警劉巖西疤,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異休溶,居然都是意外死亡代赁,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門兽掰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來芭碍,“玉大人,你說我怎么就攤上這事孽尽〗押荆” “怎么了?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵泻云,是天一觀的道長。 經(jīng)常有香客問我狐蜕,道長宠纯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任层释,我火速辦了婚禮婆瓜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘贡羔。我一直安慰自己廉白,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布乖寒。 她就那樣靜靜地躺著猴蹂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪楣嘁。 梳的紋絲不亂的頭發(fā)上磅轻,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天珍逸,我揣著相機(jī)與錄音,去河邊找鬼聋溜。 笑死谆膳,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的撮躁。 我是一名探鬼主播漱病,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼把曼!你這毒婦竟也來了杨帽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤祝迂,失蹤者是張志新(化名)和其女友劉穎睦尽,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體型雳,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡当凡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纠俭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沿量。...
    茶點(diǎn)故事閱讀 40,680評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖冤荆,靈堂內(nèi)的尸體忽然破棺而出朴则,到底是詐尸還是另有隱情,我是刑警寧澤钓简,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布乌妒,位于F島的核電站,受9級特大地震影響外邓,放射性物質(zhì)發(fā)生泄漏撤蚊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一损话、第九天 我趴在偏房一處隱蔽的房頂上張望侦啸。 院中可真熱鬧,春花似錦丧枪、人聲如沸光涂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽忘闻。三九已至,卻和暖如春恋博,著一層夾襖步出監(jiān)牢的瞬間服赎,已是汗流浹背葵蒂。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留重虑,地道東北人践付。 一個(gè)月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像缺厉,于是被迫代替她去往敵國和親永高。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容