[LeetCode] 771. Jewels and Stones
LeetCode 771. Jewels and Stones (宝石与石头) Diffculty: Eazy
Question
You’re given strings J
representing the types of stones that are jewels, and S
representing the stones you have. Each character in S
is a type of stone you have. You want to know how many of the stones you have are also jewels.
The letters in J
are guaranteed distinct, and all characters in J
and S
are letters. Letters are case sensitive, so "a"
is considered a different type of stone from "A"
.
Note:
S
andJ
will consist of letters and have length at most 50.- The characters in
J
are distinct.
给定字符串 J
代表石头中宝石的类型,和字符串 S
代表你拥有的石头。S
中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。
J
中的字母不重复,J
和 S
中的所有字符都是字母。字母区分大小写,因此 "a"
和 "A"
是不同类型的石头。
注意:
S
和J
最多含有 50 个字母。J
中的字符不重复。
Example
Example 1:
1 | Input: J = "aA", S = "aAAbbbb" |
Example 2:
1 | Input: J = "z", S = "ZZ" |
Example 3:
1 | Input: J = "AB", S = "aAAbbbbBBB" |
Solution
题意分析
- Input:字符串
J
代表石头中宝石的类型(J
中每个字符代表一种宝石类型);字符串S
代表拥有的石头(S
中每个字符代表一种石头类型) - Output:石头(
S
)中宝石的数量 - 即是需要从字符串
S
的所有字符中找到所有包含在字符串J
中的字符
Java
My Solution 1: Nested double loop
解题思路
首先将字符串(String
)转为字符数组(char[]
),然后依次遍历两个字符数组,如遍历的 J
字符数组中的元素和 S
字符数组中的元素相同,则计数 +1
解题步骤
- 字符串
J
转字符数组 ->jCharArray
- 字符串
S
转字符数组 ->sCharArray
- 定义结果变量 ->
count
- 循环 1,遍历字符数组
sCharArray
- 循环 2,嵌套在循环 1 中,遍历字符数组
jCharArray
- 循环 2 中,判断
sCharArray[i] == jCharArray[j]
,如为true
,则count++
- 循环 1 结束后,返回结果变量
Code
初版
1 | public int numJewelsInStones(String J, String S) { |
优化版
1 | public int numJewelsInStones(String J, String S) { |
Complexity Analysis
- 时间复杂度:$O(mn)$
- 空间复杂度:
My Solution 2: Hash Set (Double Loop)
解题思路
首先将字符串(String
)转为字符数组(char[]
),然后将宝石的类型(J
)存到存到哈希集合中,最后循环拥有的宝石(S
),判断在哈希集合中是否存在相同的元素。
解题步骤
- 字符串
J
转字符数组 ->jCharArray
- 定义哈希集合,遍历
jCharArray
,将字符串存进哈希集合 ->set
- 字符串
S
转字符数组 ->sCharArray
- 定义结果变量 ->
count
- 遍历字符数组
sCharArray
- 循环中,判断
set.contains(sCharArray[i])
,如为true
,则count++
- 循环结束后,返回结果变量
Code
1 | public int numJewelsInStones(String J, String S) { |
Complexity Analysis
- 时间复杂度:$O(m+n)$
- 空间复杂度:
LeetCode Discuss Solution 1: Regex (1 line)
Code
1 | public int numJewelsInStones(String J, String S) { |
Complexity Analysis
- 时间复杂度:
- 空间复杂度:
解题思路
利用 Java API 的正则表达式,从拥有的宝石 (字符串 S
) 中通过正则表达式找出所有非宝石的石头 (不在字符串 J
中),然后将非宝石的石头的字符都替换成空字符串,最后输出替换后的长度。
解题步骤
- 从字符串
S
中,通过正则表达式[^J]
,匹配所有非宝石的石头 ->tempS
- 然后把
tempS
中匹配的结果都替换成空字符串""
->tempS
- 最后输出
tempS
的长度
LeetCode Discuss Solution 2: indexOf
Code
1 | public int numJewelsInStones(String J, String S) { |
Complexity Analysis
- 时间复杂度:$O(mn)$
- 空间复杂度:
解题思路
利用 Java API 中 String 的 indexOf()
方法,遍历拥有的宝石 (字符串 S
) ,然后将字符传入 indexOf()
方法中,判断在字符串 J
中,是否有对应的宝石类型。
解题步骤
- 定义结果变量 ->
count
- 字符串
S
转字符数组 ->sCharArray
- 遍历字符数组
sCharArray
- 判断
J.indexOf(s) > -1
,如为true
,则count++
- 循环结束后,返回结果变量
注:
String 中的相关indexOf()
方法:
int indexOf(int ch)
: 返回指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。int indexOf(int ch, int fromIndex)
: 返回从 fromIndex 位置开始查找指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。int indexOf(String str)
: 返回指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。int indexOf(String str, int fromIndex)
: 返回从 fromIndex 位置开始查找指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。
Summary
一个问题的各种算法实现,也会因为编程语言的不同而呈现出不同表现方式,除了通用的思路外,也要充分了解各语言提供的 API 和特性。充分利用才能写出时间、空间复杂度都适合具体情况,且简洁易懂易维护的代码。
题中 Note 有写最多含有 50 个字母,实际上没加判断,也通过了 Testcase。
当然,实际开发中,一定要充分考虑各种边界条件和极端情况