LeetCode 随机刷题3

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;
    }
};

结果:
在这里插入图片描述

总结:这次随机刷题又是各种跪,没有一个能独立地(不看标签,不看题解)在半小时内做出来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值