LeetCode 1023: Camelcase Matching (Two-Pointer Pattern Check)
LeetCode 1023StringTwo PointersToday we solve LeetCode 1023 - Camelcase Matching.
Source: https://leetcode.com/problems/camelcase-matching/
English
Problem Summary
Given a list of query strings and a pattern, decide for each query whether we can insert lowercase letters into the pattern to get exactly that query. Any extra uppercase letter in query that is not matched by pattern makes it invalid.
Key Insight
Use two pointers for each query: i scans query and j scans pattern. When characters match, move both. If query has an unmatched lowercase letter, skip it. If query has an unmatched uppercase letter, fail immediately.
Algorithm
- For each query, set j = 0.
- Traverse each char c in query:
• if j < pattern.length and c == pattern[j], increment j.
• else if c is uppercase, return false.
- Query matches iff j == pattern.length at the end.
Complexity Analysis
Let total query length be S.
Time: O(S).
Space: O(1) extra (excluding output list).
Reference Implementations (Java / Go / C++ / Python / JavaScript)
class Solution {
public List<Boolean> camelMatch(String[] queries, String pattern) {
List<Boolean> ans = new ArrayList<>();
for (String q : queries) {
ans.add(match(q, pattern));
}
return ans;
}
private boolean match(String q, String p) {
int j = 0;
for (int i = 0; i < q.length(); i++) {
char c = q.charAt(i);
if (j < p.length() && c == p.charAt(j)) {
j++;
} else if (Character.isUpperCase(c)) {
return false;
}
}
return j == p.length();
}
}func camelMatch(queries []string, pattern string) []bool {
ans := make([]bool, len(queries))
for i, q := range queries {
ans[i] = match(q, pattern)
}
return ans
}
func match(q, p string) bool {
j := 0
for i := 0; i < len(q); i++ {
c := q[i]
if j < len(p) && c == p[j] {
j++
} else if c >= 'A' && c <= 'Z' {
return false
}
}
return j == len(p)
}class Solution {
public:
vector<bool> camelMatch(vector<string>& queries, string pattern) {
vector<bool> ans;
ans.reserve(queries.size());
for (const string& q : queries) {
ans.push_back(match(q, pattern));
}
return ans;
}
bool match(const string& q, const string& p) {
int j = 0;
for (char c : q) {
if (j < (int)p.size() && c == p[j]) {
++j;
} else if (isupper(static_cast<unsigned char>(c))) {
return false;
}
}
return j == (int)p.size();
}
};class Solution:
def camelMatch(self, queries: List[str], pattern: str) -> List[bool]:
def match(q: str, p: str) -> bool:
j = 0
for c in q:
if j < len(p) and c == p[j]:
j += 1
elif c.isupper():
return False
return j == len(p)
return [match(q, pattern) for q in queries]var camelMatch = function(queries, pattern) {
const match = (q, p) => {
let j = 0;
for (const c of q) {
if (j < p.length && c === p[j]) {
j++;
} else if (c >= 'A' && c <= 'Z') {
return false;
}
}
return j === p.length;
};
return queries.map(q => match(q, pattern));
};中文
题目概述
给你一个查询字符串数组 queries 和一个模式串 pattern。如果能在 pattern 中插入若干小写字母得到某个 query,则该 query 匹配。若 query 出现了 pattern 无法对应的额外大写字母,则一定不匹配。
核心思路
对每个 query 使用双指针:i 扫描 query,j 扫描 pattern。字符相同则两者前进;若不相同且 query 当前字符是小写,可跳过;若是大写,直接失败。
算法步骤
- 遍历每个 query,初始化 j = 0。
- 逐字符扫描 query:
• 若 j < pattern.length 且当前字符相同,j++。
• 否则若当前字符为大写,返回 false。
- 扫描结束后若 j == pattern.length 则匹配成功。
复杂度分析
设所有 query 总长度为 S。
时间复杂度:O(S)。
额外空间复杂度:O(1)(不计输出)。
多语言参考实现(Java / Go / C++ / Python / JavaScript)
class Solution {
public List<Boolean> camelMatch(String[] queries, String pattern) {
List<Boolean> ans = new ArrayList<>();
for (String q : queries) {
ans.add(match(q, pattern));
}
return ans;
}
private boolean match(String q, String p) {
int j = 0;
for (int i = 0; i < q.length(); i++) {
char c = q.charAt(i);
if (j < p.length() && c == p.charAt(j)) {
j++;
} else if (Character.isUpperCase(c)) {
return false;
}
}
return j == p.length();
}
}func camelMatch(queries []string, pattern string) []bool {
ans := make([]bool, len(queries))
for i, q := range queries {
ans[i] = match(q, pattern)
}
return ans
}
func match(q, p string) bool {
j := 0
for i := 0; i < len(q); i++ {
c := q[i]
if j < len(p) && c == p[j] {
j++
} else if c >= 'A' && c <= 'Z' {
return false
}
}
return j == len(p)
}class Solution {
public:
vector<bool> camelMatch(vector<string>& queries, string pattern) {
vector<bool> ans;
ans.reserve(queries.size());
for (const string& q : queries) {
ans.push_back(match(q, pattern));
}
return ans;
}
bool match(const string& q, const string& p) {
int j = 0;
for (char c : q) {
if (j < (int)p.size() && c == p[j]) {
++j;
} else if (isupper(static_cast<unsigned char>(c))) {
return false;
}
}
return j == (int)p.size();
}
};class Solution:
def camelMatch(self, queries: List[str], pattern: str) -> List[bool]:
def match(q: str, p: str) -> bool:
j = 0
for c in q:
if j < len(p) and c == p[j]:
j += 1
elif c.isupper():
return False
return j == len(p)
return [match(q, pattern) for q in queries]var camelMatch = function(queries, pattern) {
const match = (q, p) => {
let j = 0;
for (const c of q) {
if (j < p.length && c === p[j]) {
j++;
} else if (c >= 'A' && c <= 'Z') {
return false;
}
}
return j === p.length;
};
return queries.map(q => match(q, pattern));
};
Comments