Skip to content

Commit 151543f

Browse files
authored
Merge pull request gzc426#157 from Longerhaha/master
更新890_(查找和替换模式)Find and Repalce Pattern解题描述到乔戈里leetcode每日一题库
2 parents d283e51 + ac05ff1 commit 151543f

File tree

4 files changed

+156
-2
lines changed

4 files changed

+156
-2
lines changed

2018.11.30-leetcode890/1.md

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
## 890_(查找和替换模式)Find and Repalce Pattern
2+
## 1 问题描述、输入输出与样例
3+
### 1.1 问题描述
4+
你有一个单词列表 words 和一个模式 pattern,你想知道 words 中的哪些单词与模式匹配。<br>
5+
如果存在字母的排列 p ,使得将模式中的每个字母 x 替换为 p(x) 之后,我们就得到了所需的单词,那么单词与模式是匹配的。<br>
6+
(回想一下,字母的排列是从字母到字母的双射:每个字母映射到另一个字母,没有两个字母映射到同一个字母。)<br>
7+
返回 words 中与给定模式匹配的单词列表。<br>
8+
你可以按任何顺序返回答案。<br>
9+
__提示__:<br>
10+
1. 1 <= words.length <= 50<br>
11+
2. 1 <= pattern.length = words[i].length <= 20<br>
12+
### 1.2 输入与输出
13+
输入:<br>
14+
* vector<string>& words:给定的单词列表<br>
15+
* string pattern:模式单词<br>
16+
输出:<br>
17+
* vector<string>:与给定模式匹配的单词列表<br>
18+
19+
### 1.3 样例
20+
#### 1.3.1 样例1
21+
输入: <br>
22+
words = ["abc","deq","mee","aqq","dkd","ccc"], pattern = "abb"<br>
23+
24+
输出: <br>
25+
["mee","aqq"]<br>
26+
27+
解释:<br>
28+
"mee" 与模式匹配,因为存在排列 {a -> m, b -> e, ...}。<br>
29+
"ccc" 与模式不匹配,因为 {a -> c, b -> c, ...} 不是排列。
30+
因为 a 和 b 映射到同一个字母。<br>
31+
## 2 思路描述与代码
32+
### 2.1 思路描述(双字典方法)
33+
对每个属于单词列表words的单词word,使用dict1 记录 word 中的字符 word[i] 对 pattern 字符 pattern[i] 的映射<br>
34+
使用dict2 记录 pattern 中的字符 pattern[i] 对 word 字符 word[i] 的映射<br>
35+
```cpp
36+
for(word in words){
37+
初始化字典映射;
38+
for(word[i] in word){
39+
if(word[i] 未被映射)
40+
if(pattern[i] 未被映射) 双方记录映射关系;
41+
else 确认 pattern[i] 映射的对象是不是 word[i],如果不是则失败;
42+
if(word[i] 已被映射 且 映射对象不是 pattern[i]) 则失败;
43+
}
44+
如果成功,记录word;
45+
}
46+
```
47+
48+
### 2.2 代码
49+
```cpp
50+
vector<string> findAndReplacePattern(vector<string>& words, string pattern) {
51+
vector<string> ans;
52+
for( auto word : words ){
53+
// dict1 记录 word 中的字符对 pattern 字符的映射
54+
// dict2 记录 pattern 中的字符对 word 字符的映射
55+
vector<int> dict1(127, -1);
56+
vector<int> dict2(127, -1);
57+
int word_len = word.size();
58+
int fail = 0;
59+
for( int i = 0; i < word_len; i++ ){
60+
// 如果 word[i] 未被映射
61+
// (i) 如果 pattern[i] 未被映射,双方记录映射关系
62+
// (ii) 如果 pattern[i] 已被映射,确认 pattern[i] 映射的对象是不是 word[i],如果不是则失败
63+
if(dict1[word[i]] == -1){
64+
if(dict2[pattern[i]] == -1){
65+
dict1[word[i]] = pattern[i];
66+
dict2[pattern[i]] = word[i];
67+
}
68+
else if(dict2[pattern[i]] != word[i]){
69+
fail = 1;
70+
break ;
71+
}
72+
}
73+
// 如果 word[i] 已被映射 且 映射对象不是 pattern[i],则失败
74+
else if(dict1[word[i]] != -1 && dict1[word[i]] != pattern[i]){
75+
fail = 1;
76+
break ;
77+
}
78+
}
79+
//如果成功,记录word
80+
if(!fail) ans.push_back(word);
81+
}
82+
return ans;
83+
}
84+
```
85+
## 3 思考与拓展
86+
### 3.1 思考
87+
#### 3.1.1 其他方法
88+
无。
89+
#### 3.1.2 复杂度分析
90+
方法|空间复杂度|时间复杂度
91+
--- | --- | ---
92+
双字典方法|O(1)|O(kn),k为word的长度,n为words的数目
93+
#### 3.1.3 难点分析
94+
1. 如何记录二者的映射关系;
95+
2. 如何分辨映射存在一对多、多对一和多对多情况的出现。
96+
97+
### 3.1 扩展
98+
本题需要使用两个字典记录映射关系,不然可能导致一对多或者多对一情况。
99+

2018.12.1-leetcode387/1.md

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
## 387_(字符串中的第一个唯一字符)First Unique Character in a String
2+
## 1 问题描述、输入输出与样例
3+
### 1.1 问题描述
4+
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
5+
### 1.2 输入与输出
6+
输入:
7+
* string s:输入的字符串 s
8+
9+
输出:
10+
* int:它的第一个不重复的字符的索引
11+
### 1.3 样例
12+
#### 1.3.1 样例1
13+
输入:s = "leetcode"<br>
14+
输出:返回 0<br>
15+
16+
#### 1.3.2 样例2
17+
输入: s = "loveleetcode"<br>
18+
输出: 2<br>
19+
## 2 思路描述与代码
20+
### 2.1 思路描述(字典法)
21+
dict[c] 记录字符 c 的数目,一遍扫描记录字符串 s 中的所有字符的数目<br>
22+
然后再一遍扫描 s,当 s 中字符 c 只出现一次即dict[c] = 1时返回下标,如果没有这样的字符则返回-1<br>
23+
24+
比如输入s = "leetcode",一遍扫描后有:<br>
25+
dict['c'] = 1, dict['d'] = 1, dict['e'] = 3, dict['l'] = 1, dict['o'] = 1, dict['t'] = 1<br>
26+
然后再次一遍扫描s,发现dict['l'] = 1,返回此时遍历的索引 0<br>
27+
28+
### 2.2 代码
29+
```cpp
30+
int firstUniqChar(string s) {
31+
vector<int> dict(26, 0);
32+
int len = s.size();
33+
for( int i = 0; i < len; i++ ) dict[s[i] - 'a'] += 1;
34+
for( int i = 0; i < len; i++ ){
35+
if(dict[s[i] - 'a'] == 1) return i;
36+
}
37+
return -1;
38+
}
39+
```
40+
## 3 思考与拓展
41+
### 3.1 思考
42+
#### 3.1.1 其他方法
43+
##### 3.1.1.1 字典+队列法
44+
dict[c] 记录字符 c 的数目,队列 q 保存的是在遍历过程中在 s 中按前后顺序出现出现过的字符极其下标,相同字符只记录一次<br>
45+
46+
然后遍历队列里面的元素,当 s 中字符 c 只出现一次即dict[c] = 1时返回下标。
47+
48+
#### 3.1.2 复杂度分析
49+
方法|空间复杂度|时间复杂度
50+
--- | --- | ---
51+
字典法|O(1)|O(n)
52+
字典+队列法|O(n)|O(n),平均复杂度更低,应该运行更快
53+
#### 3.1.3 难点分析
54+
1. 如何查重即多个相同的字符
55+
2. 如何按先后顺序记录只出现一次的字符
56+
### 3.2 拓展
57+
如果给你的是链表数据或者数组数据呢?

0 commit comments

Comments
 (0)