【leetcode】古生物血缘远近判定

191 阅读1分钟

题目来源

leetcode.cn/leetbook/re…

问题描述

DNA 是由 ACGT 四种核苷酸组成,例如 AAAGTCTGAC,假定自然环境下 DNA 发生异变的情况有:

  1. 基因缺失一个核苷酸
  2. 基因新增一个核苷酸
  3. 基因替换一个核苷酸

且发生概率相同。

古生物学家 Sam 得到了若干条相似 DNA 序列,Sam 认为一个 DNA 序列向另外一个 DNA 序列转变所需的最小异变情况数可以代表其物种血缘相近程度,异变情况数越少,血缘越相近,请帮助 Sam 实现获取两条 DNA 序列的最小异变情况数的算法。


解法

直接使用二维DP操作,有两种操作,如果字符相等,等于上一个状态,如果不相等,看一下是替换?还是删除,删除的情况分成两种,如图所示:

image.png

定义dp[i][j] 表示 dna1 中前 i 个字符变成 dna2 中前j个字符最少需要多少步。

容易从图中看出相应的状态转移。

//dp[i][j] 表示 dna1 中前 i 个字符变成 dna2 中前j个字符最少需要多少步
package main

import (
	"fmt"
	"strings"
)

func main() {
    var s string

    fmt.Scan(&s)
	s11 := strings.Split(s, ",")
	s1 := s11[0]
	s2 := s11[1]
    dp := make([][]int, len(s1)+1)
    for i:=0;i<=len(s1);i++{
        dp[i] = make([]int, len(s2)+1)
    }

    for i:=1;i<=len(s1);i++{
        dp[i][0] = i
    }
    for i:=1;i<=len(s2);i++{
        dp[0][i] = i
    }

    for i :=1;i<=len(s1);i++{
        for j:=1;j<=len(s2);j++{
            if s1[i-1] == s2[j-1]{
                //相等,不变
                dp[i][j] = dp[i-1][j-1]
            }else{
                //不相等,根据题目的意思有三种思路.
                dp[i][j] = min(dp[i-1][j-1] + 1, dp[i][j-1]+1)
                dp[i][j] = min(dp[i][j], dp[i-1][j] + 1)
            }
        }
    }
    fmt.Print(dp[len(s1)][len(s2)])
}

func min(x, y int) int{
    if x > y{
        return y
    }
    return x
}