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();
}
Category >> Algorithms >> Interview  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>
  • amitabh suman

    That solution takes O(mn) space. This one takes O(1) space.

  • Sreeparna Mukherjee
  • Sudhakar R

    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;

    }

    }

  • Matias SM

    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”;

  • Matias SM

    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;
    }

  • José Yánez

    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?

  • Guus

    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.

  • Sam

    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;
    }

  • Sam

    this will fail for input “aaaabbbbcccc” “a*”

  • NB****


    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";

  • typing..

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