2022-6-27 信物传送,最长特殊序列II,T秒后青蛙的位置

1. 信物传送

欢迎各位勇者来到力扣城,本次试炼主题为「信物传送」。

本次试炼场地设有若干传送带,matrix[i][j] 表示第 ij 列的传送带运作方向,"^","v","<",">" 这四种符号分别表示 上、下、左、右 四个方向。信物会随传送带的方向移动。勇者每一次施法操作,可临时变更一处传送带的方向,在物品经过后传送带恢复原方向。

通关信物初始位于坐标 start处,勇者需要将其移动到坐标 end 处,请返回勇者施法操作的最少次数。

Example

输入:matrix = [">>v","v^<","<><"], start = [0,1], end = [2,0]
输出:1

代码 [01BFS]

class Solution {
private:
    int DIR[4][2]{{-1, 0}, {1,  0}, {0,  -1}, {0,  1},};
    char SIG[4]{'^', 'v', '<', '>'};
    int dist[100][100];
    bool visited[100][100];

public:
    int conveyorBelt(vector<string> &matrix, vector<int> &start, vector<int> &end) {
        int n = matrix.size(), m = matrix[0].size();
        memset(dist, 0x3f, sizeof dist);
        memset(visited, 0, sizeof visited);
        deque<pair<int, int>> deq;
        deq.emplace_back(start[0], start[1]);
        dist[start[0]][start[1]] = 0;
        while (!deq.empty()) {
            auto[x, y]=deq.front();
            deq.pop_front();
            if (visited[x][y]) continue;
            if (x == end[0] && y == end[1]) break;
            visited[x][y] = true;
            for (int i = 0; i < 4; ++i) {
                int nx = x + DIR[i][0], ny = y + DIR[i][1];
                if (nx < 0 || ny < 0 || nx == n || ny == m) continue;
                int ndist = dist[x][y] + (SIG[i] != matrix[x][y]);
                if (ndist >= dist[nx][ny]) continue;
                dist[nx][ny] = ndist;
                SIG[i] != matrix[x][y] ? deq.emplace_back(nx, ny) : deq.emplace_front(nx, ny);
            }
        }
        return dist[end[0]][end[1]];
    }
};

2. 最长特殊序列 II

Given an array of strings strs, return the length of the longest uncommon subsequence between them. If the longest uncommon subsequence does not exist, return -1.

An uncommon subsequence between an array of strings is a string that is a subsequence of one string but not the others.

Example

Input: strs = ["aba","cdc","eae"]
Output: 3

代码

class Solution:
    def findLUSlength(self, strs: List[str]) -> int:
        def is_sub_str(s1: str, s2: str) -> bool:
            if len(s2) < len(s1): return False
            i = j = 0
            while i < len(s1) and j < len(s2):
                if s1[i] == s2[j]: i += 1
                j += 1
            return i == len(s1)
        
        ans = -1
        for i, s in enumerate(strs):
            if len(s) > ans and all(not is_sub_str(s, s_) for j, s_ in enumerate(strs) if j != i):
                ans = len(s)
        return ans

3. T 秒后青蛙的位置

给你一棵由 n 个顶点组成的无向树,顶点编号从 1 到 n。青蛙从 顶点 1 开始起跳。规则如下:

  • 在一秒内,青蛙从它所在的当前顶点跳到另一个 未访问 过的顶点(如果它们直接相连)。

  • 青蛙无法跳回已经访问过的顶点。

  • 如果青蛙可以跳到多个不同顶点,那么它跳到其中任意一个顶点上的机率都相同。

  • 如果青蛙不能跳到任何未访问过的顶点上,那么它每次跳跃都会停留在原地。

无向树的边用数组 edges 描述,其中 edges[i] = [fromi, toi] 意味着存在一条直接连通 fromitoi 两个顶点的边。

返回青蛙在 t 秒后位于目标顶点 target 上的概率。

Example

输入:n = 7, edges = [[1,2],[1,3],[1,7],[2,4],[2,6],[3,5]], t = 2, target = 4
输出:0.16666666666666666 

代码 [BFS]

class Solution {
private:
    bool visited[101], isEnd[101];
    int time[101];
    double prob[101];

public:
    double frogPosition(int n, vector<vector<int>> &edges, int t, int target) {
        memset(visited, 0, sizeof visited);
        memset(isEnd, 0, sizeof isEnd);
        memset(time, 0, sizeof time);
        memset(prob, 0, sizeof prob);
        prob[1] = 1;
        unordered_map<int, unordered_set<int>> mp;
        for (auto &edge:edges) {
            mp[edge[0]].insert(edge[1]);
            mp[edge[1]].insert(edge[0]);
        }
        queue<int> q;
        q.push(1);
        while (!q.empty()) {
            int node = q.front();
            q.pop();
            visited[node] = true;
            int children = 0;
            for (auto next:mp[node]) {
                if (!visited[next]) children++;
            }
            if (children == 0) {
                isEnd[node] = true;
                continue;
            }
            double np = prob[node] / children;
            for (auto next:mp[node]) {
                if (visited[next]) continue;
                prob[next] = np;
                time[next] = time[node] + 1;
                q.push(next);
            }

        }
        if (t < time[target]) return 0;
        if (t == time[target] || isEnd[target]) return prob[target];
        return 0;
    }
};

代码 2 [BFS-剪枝]

class Solution {
private:
    bool visited[101];
    int time[101];
    double prob[101];

public:
    double frogPosition(int n, const vector<vector<int>> &edges, int t, int target) {
        memset(visited, 0, sizeof visited);
        memset(time, 0, sizeof time);
        memset(prob, 0, sizeof prob);
        prob[1] = 1;
        vector<vector<int>> mp(n + 1);
        for (auto &edge:edges) {
            mp[edge[0]].push_back(edge[1]);
            mp[edge[1]].push_back(edge[0]);
        }
        queue<int> q;
        q.push(1);
        while (!q.empty()) {
            int node = q.front();
            q.pop();
            visited[node] = true;
            int children = 0;
            for (auto next:mp[node]) {
                if (!visited[next]) children++;
            }
            if (children == 0) {
                if (target == node) return t >= time[node] ? prob[node] : 0;
                continue;
            } else {
                if (target == node) return t == time[node] ? prob[node] : 0;
            }
            double np = prob[node] / children;
            for (auto next:mp[node]) {
                if (visited[next]) continue;
                prob[next] = np;
                time[next] = time[node] + 1;
                q.push(next);
            }

        }
        return t == time[target] ? prob[target] : 0;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值