力扣字符串练习题(通配符匹配、字母异位词分组)

148 阅读1分钟

通配符匹配

来源:力扣(LeetCode) 链接:leetcode.cn/problems/wi…

给你一个输入字符串 (s) 和一个字符模式 (p) ,请你实现一个支持 '?' 和 '*' 匹配规则的通配符匹配:

  • '?' 可以匹配任何单个字符。
  • '*' 可以匹配任意字符序列(包括空字符序列)。

判定匹配成功的充要条件是:字符模式必须能够 完全匹配 输入字符串(而不是部分匹配)。

示例 1:

输入:s = "aa", p = "a"

输出:false

解释:"a" 无法匹配 "aa" 整个字符串。

示例 2:

输入:s = "aa", p = "*"

输出:true

解释:'*' 可以匹配任意字符串。

示例 3:

输入:s = "cb", p = "?a"

输出:false

解释:'?' 可以匹配 'c', 但第二个 'a' 无法匹配 'b'

提示:

  • 0 <= s.length, p.length <= 2000
  • s 仅由小写英文字母组成
  • p 仅由小写英文字母、'?' 或 '*' 组成

代码

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

思路分析

  1. 创建一个二维数组dp,用于存储匹配状态。dp[i][j]表示s的前i个字符与p的前j个字符是否匹配。

  2. 初始化dp[0][0]为true,表示空字符串与空模式匹配。

  3. 遍历模式p,如果当前字符为*,则将dp[0][j]设为与前一个字符匹配的状态。

  4. 使用两层循环遍历字符串s和模式p的每个字符,从1开始。

  5. 如果当前字符s[i-1]和模式字符p[j-1]相等,或者模式字符p[j-1]为?,则将dp[i][j]设为dp[i-1][j-1],表示当前字符匹配。

  6. 如果模式字符p[j-1]为*,则有两种情况可以匹配成功:

    • 使用*匹配空字符串,即dp[i][j] = dp[i][j-1]
    • 使用*匹配当前字符,即dp[i][j] = dp[i-1][j]
  7. 最终返回dp[m][n],其中m为字符串s的长度,n为模式p的长度。

字母异位词分组

来源:力扣(LeetCode) 链接:leetcode.cn/problems/gr…

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。

示例 1:

输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]

输出: [["bat"],["nat","tan"],["ate","eat","tea"]]

示例 2:

输入: strs = [""]

输出: [[""]]

示例 3:

输入: strs = ["a"]

输出: [["a"]]

提示:

  • 1 <= strs.length <= 104
  • 0 <= strs[i].length <= 100
  • strs[i] 仅包含小写字母

代码

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> map = new HashMap<>();
        
        for (String str : strs) {
            char[] chars = str.toCharArray();
            Arrays.sort(chars);
            String sortedStr = String.valueOf(chars);
            
            if (!map.containsKey(sortedStr)) {
                map.put(sortedStr, new ArrayList<>());
            }
            map.get(sortedStr).add(str);
        }
        
        return new ArrayList<>(map.values());
    }
}

思路分析

  1. 创建一个HashMap,用于存储字母异位词分组的结果。键为排序后的字符串,值为该分组中的所有字符串。
  2. 遍历字符串数组strs,对于每个字符串str,将其转换为字符数组,并对字符数组进行排序。
  3. 将排序后的字符数组转换为字符串sortedStr。
  4. 如果map中不包含sortedStr作为键,说明是一个新的字母异位词分组,需要创建一个新的列表,并将sortedStr作为键,将新列表添加到map中。
  5. 如果map中已经包含sortedStr作为键,说明是一个已存在的字母异位词分组,直接将当前字符串str添加到对应的列表中。
  6. 最终将map中的所有值转换为列表,并返回结果。