LeetCode433. 最小基因变化


LeetCode433. 最小基因变化

题目描述

本题目来自 LeetCode 上的『433. 最小基因变化』

一组基因序列由8个字符组成。一次基因变化定义为 基因序列中的一个字符 发生变化。
bank 中为所有合法的基因变化,求基因 startend 需要经历几次基因变化。

示例 1:

输入:start = “AACCGGTT”, end = “AACCGGTA”, bank = [“AACCGGTA”]

输出:1

示例 2:

输入:start = “AAAAACCC”, end = “AACCCCCC”, bank = [“AAAACCCC”,”AAACCCCC”,”AACCCCCC”]

输出:3

提示:
  • start.length == 8
  • end.length == 8
  • 0 <= bank.length <= 10
  • bank[i].length == 8
  • startendbank[i] 仅由字符 ['A', 'C', 'G', 'T'] 组成

题解—预处理+BFS

我们用 $0,1,2,…$ 为bank 中的基因编号,以这些编号为顶点建无向图,建图规则如下:

  • 如果两个基因序列的 距离 为1,即两个基因序列只有一个字符不同,那么就在这两个顶点之间加上一条边。
  • 为了方便搜索,我们将基因序列 start 也加入到 bank 的末尾。

建图完毕后,问题就转化成求 start 所在点 xend 所在点 y 之间的最小距离,如果两点不连通就返回 -1
无权值图的单源最短路径可以使用 BFS。

代码

class Solution {
private:
    vector<vector<int>> graph;
    int distance(const string& s1, const string& s2) {
        int dist = 0;
        for (int i = 0; i < (int)s1.size(); ++i) {
            if (s1[i] != s2[i]) {
                ++dist;
            }
        }
        return dist;
    }
    void build(const vector<string>& bank) {
        int n = bank.size();
        for (int i = 0; i < n; ++i) {
            for (int j = i + 1; j < n; ++j) {
                if (distance(bank[i], bank[j]) == 1) {
                    graph[i].emplace_back(j);
                    graph[j].emplace_back(i);
                }
            }
        }
    }

    int bfs(int x, int y, int n) {
        vector<bool> visited(n, false);
        queue<int> q;
        q.emplace(x);
        visited[x] = true;
        int ans = 0;
        while (!q.empty()) {
            for (int i = q.size(); i > 0; --i) {
                int poll = q.front();
                q.pop();
                if (poll == y) {
                    return ans;
                }
                for (const auto& v : graph[poll]) {
                    if (!visited[v]) {
                        q.emplace(v);
                        visited[v] = true;
                    }
                }
            }
            ++ans;
        }
        return -1;
    }

public:
    int minMutation(string start, string end, vector<string>& bank) {
        bank.emplace_back(start);
        int n = bank.size();
        graph.resize(n);
        build(bank);
        int idx = -1;
        for (int i = 0; i < n; ++i) {
            if (bank[i] == end) {
                idx = i;
                break;
            }
        }
        return bfs(n - 1, idx, n);
    }
};

复杂度分析

  • 时间复杂度:设 bank 长度为 $n$,基因序列长度为 $m$,则建图的复杂度为 $O(m\times n^2)$,搜索时,最多搜索 $n$ 个顶点,因此搜索的复杂度为 $n$,综合复杂度为 $O(m\times n^2)$
  • 空间复杂度 $O(n^2)$

文章作者: xitie2000
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 xitie2000 !
评论
  目录