1643. 第 K 条最小指令
只会用暴力的,没有刷,看了题解,需要用到组合数。以后可以重复刷。
这里记录一下组合数的求法,
c
o
m
b
[
n
]
[
m
]
comb[n][m]
comb[n][m]为从n个数中选取m个的组合方式(n > m)。
vector<vector<int>> comb(n + 1, vector<int>(m + 1));
comb[0][0] = 0;
for(int i = 0; i <= n; i++){
cor(int j = 0; j <= i && j <= m; j++){
comb[i][j] = comb[i - 1][j - 1] + comb[i - 1][j];
}
}
792. 匹配子序列的单词数
难度:中等。
标签:数组。
这个题暴力很简单,但会超时。
观察S的最大长度和words的最大个数,来找优化办法。
S长度很长,因此如果把S的信息记录下来即可优化。
用一个二维数组记录S信息,数组大小为
v
e
c
[
S
.
l
e
n
g
t
h
]
[
26
]
vec[S.length][26]
vec[S.length][26],使用
v
e
c
[
i
]
[
j
]
vec[i][j]
vec[i][j]表示S中第i个字符的下一个
c
h
a
r
(
′
a
′
+
j
)
char('a'+j)
char(′a′+j)字符的位置。
还有一种方法是将words中重复串的个数记录下来,使用
m
a
p
<
s
t
r
i
n
g
,
i
n
t
>
map<string,int>
map<string,int>每个字符串的个数。
然后对map->first进行遍历,若map->first是s的子串,则result += map->second。
要仔细观察数据的取值范围,大小,针对数据特定对算法进行优化改进。
正确解法:
class Solution {
public:
int numMatchingSubseq(string s, vector<string>& words) {
int result = 0;
unordered_map<string, int> mymap;
for(int i = 0; i < words.size(); i++){
if(mymap.find(words[i]) == mymap.end()){
mymap[words[i]] = 1;
}
else{
mymap[words[i]] += 1;
}
}
for(auto it = mymap.begin(); it != mymap.end(); it++){
string t = it->first;
int idx = 0;
for(int i = 0; i < s.length(); i++){
if(s[i] == t[idx])idx++;
if(idx >= t.length()){
result += it->second;
break;
}
}
}
return result;
}
};
结果:
375. 猜数字大小 II
难度:中等。
标签:动态规划,极小化极大。
刚开始以为二分法中取最大可以解决,发现使用二分法根本推不出答案。因此二分法的思维是错的。
正确解法:
class Solution {
public:
int getMoneyAmount(int n) {
vector<vector<int>> dp(n + 1, vector<int> (n + 1));
for(int step = 1; step < n; step++){
for(int i = 1; i <= n - step; i++){
int j = i + step;
dp[i][j] = i + dp[i + 1][j];
for(int k = i + 1; k <= j; k++){
if(k == j){
dp[i][j] = min(dp[i][j], dp[i][j - 1] + j);
}
else{
dp[i][j] = min(dp[i][j], max(dp[i][k - 1],dp[k + 1][j]) + k);
}
}
}
}
return dp[1][n];
}
};
结果:
815. 公交路线
难度:困难。
标签:广度优先搜索。
果然题目挖的坑,我都能顺利载进去。
不应该用公交车站作为图上的点,而应该使用公交车一条线路作为图上的点。
这样的话出发点和目标点其实有多个。
先贴一个把公交站作为图上点的做法,第5个用例就超时,太狠了。
class Solution {
unordered_map<int, int> mymap;
vector<vector<int>> graph;
int result = -1;
void bfs(int now_i, int target_i, vector<int>& path, int len){
if(result != -1 && len >= result){
return;
}
if(now_i == target_i){
if(result == -1 || result > len){
result = len;
}
return;
}
path[now_i] = 1;
for(int i = 0; i < graph[now_i].size(); i++){
int stop = graph[now_i][i];
int stop_i = mymap[stop];
if(path[stop_i] == 0){
bfs(stop_i, target_i, path, len + 1);
}
}
path[now_i] = 0;
}
public:
int numBusesToDestination(vector<vector<int>>& routes, int source, int target) {
int idx = 0;
for(int i = 0; i < routes.size(); i++){
if(routes[i].size() <= 1)continue;
for(int j = 0; j < routes[i].size(); j++){
int stop = routes[i][j];
if(mymap.find(stop) == mymap.end()){
mymap[stop] = idx;
idx++;
vector<int> temp;
for(int k = 0; k < routes[i].size(); k++){
if(k == j)continue;
temp.push_back(routes[i][k]);
}
graph.push_back(temp);
}
else{
int stop_i = mymap[stop];
for(int k = 0; k < routes[i].size(); k++){
if(k == j)continue;
graph[stop_i].push_back(routes[i][k]);
}
}
}
}
for(int i = 0; i < graph.size(); i++){
sort(graph[i].begin(),graph[i].end());
graph[i].erase(unique(graph[i].begin(),graph[i].end()),graph[i].end());
}
if(mymap.find(source) == mymap.end() || mymap.find(target) == mymap.end()){
return -1;
}
/*for(auto it = mymap.begin(); it != mymap.end(); it++){
cout << it->first << " " << it->second << endl;
}
for(int i = 0; i < graph.size(); i++){
for(int j = 0; j < graph[i].size(); j++){
cout << graph[i][j] << " ";
}
cout << endl;
}
cout << idx << endl;
cout << "---------------\n";
*/
vector<int> path(idx);
bfs(mymap[source], mymap[target], path, 0);
return result;
}
};
这个是我看过的最简单的C++代码,使用map来存储每个车站经过的路线的集合,然后直接就可以进行遍历。使用队列来存储当前所在的路线索引,每次将当前路线的所有车站遍历一遍,若找到target返回,否则将这些车站能到达的路线再次push进队列。
正确解法:
class Solution {
public:
int numBusesToDestination(vector<vector<int>>& routes, int source, int target) {
if(source == target)return 0;
int n = routes.size();
// 存储每个车站经过的路线
map<int, set<int>> mymap;
for(int i = 0; i < n; i++){
for(auto j : routes[i]){
mymap[j].insert(i);
}
}
queue<int> q;
vector<int> visited(n);
for(auto route : mymap[source]){
q.push(route);
visited[route] = 1;
}
int result = 0;
int flag = 0;
while(!q.empty()){
int size = q.size();
result++;
for(int i = 0; i < size; i++){
int route = q.front();
q.pop();
for(int k = 0; k < routes[route].size(); k++){
int stop = routes[route][k];
if(stop == target){
flag = 1;
break;
}
for(auto j:mymap[stop]){
if(visited[j] == 0){
q.push(j);
visited[j] = 1;
}
}
}
}
if(flag)break;
}
if(flag)return result;
return -1;
}
};
结果:
总结:这次随机刷题又是各种跪,没有一个能独立地(不看标签,不看题解)在半小时内做出来。