LeetCode – Wildcard Matching (Java)

Implement wildcard pattern matching with support for ‘?’ and ‘*’.

Java Solution

To understand this solution, you can use s=”aab” and p=”*ab”.

public boolean isMatch(String s, String p) {
	int i = 0;
	int j = 0;
	int starIndex = -1;
	int iIndex = -1;
 
	while (i < s.length()) {
		if (j < p.length() && (p.charAt(j) == '?' || p.charAt(j) == s.charAt(i))) {
			++i;
			++j;
		} else if (j < p.length() && p.charAt(j) == '*') {
			starIndex = j;		
			iIndex = i;
			j++;
		} else if (starIndex != -1) {
			j = starIndex + 1;
			i = iIndex+1;
			iIndex++;
		} else {
			return false;
		}
	}
 
	while (j < p.length() && p.charAt(j) == '*') {
		++j;
	}
 
	return j == p.length();
}

14 thoughts on “LeetCode – Wildcard Matching (Java)”

  1. public static boolean isMatch(String a, String b){

    if(a == null || b == null){

    return false;
    }

    if(a.length() != b.length()){

    return false;
    }

    for( int i=0 ; i < a.length() ; i++){

    char c1 = a.charAt(i);
    char c2 = b.charAt(i);

    if( c2 != '*' && c2 != '?'){

    if(c1 != c2){
    return false;
    }
    }
    }

    return true;
    }

  2. There are too many cases where this might fail, though it works fine for the example taken above.
    like if s=a and p=*aab, this will fail

  3. very Simple understanding solution replace “.” with “?”

    /* package whatever; // don’t place package name! */

    import java.util.*;

    import java.lang.*;

    import java.io.*;

    /* Name of the class has to be “Main” only if the class is public. */

    class Ideone

    {

    public static void main (String[] args) throws java.lang.Exception

    {

    //System.out.println(isMatchMain(“.”,”a”));

    System.out.println(isMatchMain(“abc*bcd”, “abcdhghgbcd”));

    }

    public static boolean isMatchMain(String P, String S) {

    if(P == null || S == null || P.length() == 0 || S.length() == 0) return false;

    return isMatch( P, S);

    }

    public static boolean isMatch(String P, String S) {

    if(P.length() == 0 && S.length() == 0) {

    return true;

    }

    if(S.length() == 0 && !P.equals(“*”)) return false;

    if(isCharEqual(‘.’, P) || equalsString(P, S)) {

    return isMatch(P.substring(1), S.substring(1));

    }

    if(isCharEqual(‘*’, P)) {

    return isMatch(P.substring(1), S) || isMatch(P, S.substring(1));

    }

    return false;

    }

    public static boolean isCharEqual(char ch, String S) {

    if(S.length() > 0 && ch == S.charAt(0)) return true;

    return false;

    }

    public static boolean equalsString(String P, String S) {

    if(P.length() > 0 && S.length() > 0 && S.charAt(0) == P.charAt(0)) return true;

    return false;

    }

    }

  4. I believe it is Processing O(N^2) (N square) and Space O(1).

    Is N^2 in the following pathological case:
    String s = “aaaaaaaaab”;
    String p = “*aaaaaaaaz”;

  5. I think a clarification is in order here, in some regex patterns the meaning of the special chars is:
    ?: zero or one occurrence of the _previous_ char
    *: zero or more occurrence of the _previous_ char.
    Also you should say which greediness logic is used (for ‘*’). Normally * is greedy, that is, it “consumes” as much from the input string as possible.

    Here is my solution for the above specified logic (which I understand is not the same used in the example solution):
    Note: this assumes the existence of a special “non-valid” char (used ”) which may not be a valid assumption. Can be adapted to avoid this (e.g. using null and Character). Also, provides some validations for the pattern expression.


    boolean isMatch(String str, String pattern) {
    if (str.isEmpty() ^ pattern.isEmpty()) return false;
    int matchingSpecialRemaining = 0;
    char matchingChar = '';

    int i = 0;
    int p = 0;
    while (i p && matchingSpecialRemaining == 0) {
    matchingChar = pattern.charAt(p);
    //may add check for special char for sanity (invalid expression)
    ++p;
    if (pattern.length() > p) { //look ahead for a special char
    switch (pattern.charAt(p)) {
    case '?':
    matchingSpecialRemaining = 1;
    ++p;
    break;
    case '*':
    matchingSpecialRemaining = -1;
    ++p;
    break;
    }
    }
    } else if (matchingSpecialRemaining == 0) {
    matchingChar = ''; //or some other invalid char
    }
    if (str.charAt(i) == matchingChar) {
    if (matchingSpecialRemaining == 1) matchingSpecialRemaining = 0;
    ++i;
    } else {
    if (matchingSpecialRemaining == 0) return false;
    else matchingSpecialRemaining = 0;
    }
    }
    //we completed the str, need to check if there is still pattern to match
    while (p < pattern.length()) {
    int next = p + 1;
    //if there is a char but no wildcard, pattern not matched
    if ((pattern.length() <= next) || (pattern.charAt(next) != '*' && pattern.charAt(next) != '?') )
    return false;
    p = next + 1;
    }
    return true;
    }

  6. Notice there’s no if (p == s) return p; at the first line, I mean don’t you want to see if they’re equal?

  7. This fails because the test p.charAt(j) == s.charAt(i) can cause a * in p to be regarded as a normal character if there is also a * in s.

  8. public static boolean isMatch(String s, String p) {
    if (s.isEmpty() && p.isEmpty()) return true;
    if (p.isEmpty()) return false;
    if (s.isEmpty()) {
    return isAllStar(p);
    }

    char sC = s.charAt(0);
    char pC = p.charAt(0);
    if (pC == '*') {
    boolean res = isMatch(s, p.substring(1));
    if (!res) {
    res = isMatch(s.substring(1), p);
    }
    return res;
    } else if (pC == '?' || sC == pC) {
    return isMatch(s.substring(1), p.substring(1));
    }
    return false;
    }

    private static boolean isAllStar(final String p) {
    for (char c : p.toCharArray()) {
    if (c != '*') return false;
    }
    return true;
    }


  9. string s = "acab";

    string p = "?*b";

    size_t i = 0, j = 0;

    bool wildcard = true;

    while (i < s.length()) {

    if (s[i] == p[j] || p[j] == '?') {

    i++;

    j++;

    } else if (p[j] == '*') {

    size_t found = s.find_first_of(p[j+1], i);

    if (found != string::npos) {

    j = j + 2;

    i = found + 1;

    continue;

    } else {

    wildcard = false;

    break;

    }

    } else {

    wildcard = false;

    break;

    }

    }

    cout << "Is wild card: " << wildcard << "n";

  10. You should also post some detailing like Time and Space Complexity of the solution.. although its fine..

Leave a Comment