AI刷题DNA序列编辑距离|豆包MarsCode AI刷题

43 阅读4分钟

问题解析

问题描述

小R正在研究DNA序列转换问题。目标是将一个受损的DNA序列(dna1)转换为一个未受损的序列(dna2)。转换的步骤包括:

  • 增加一个碱基:在dna1中插入一个碱基,使其更接近dna2
  • 删除一个碱基:从dna1中删除一个碱基,使其更接近dna2
  • 替换一个碱基:将dna1中的一个碱基替换为另一个碱基,使其更接近dna2

目标是找到将dna1转换为dna2所需的最少编辑步骤数。

测试样例解析

样例1:

  • 输入: dna1 = "AGT", dna2 = "AGCT"
  • 输出: 1
  • 解析:
    • AGT末尾插入C,得到AGCT
    • 最少编辑步骤数为1。

样例2:

  • 输入: dna1 = "AACCGTT", dna2 = "AACCTTG"
  • 输出: 4
  • 解析:
    • 需要进行多次插入、删除或替换操作。
    • 最少编辑步骤数为4。

样例3:

  • 输入: dna1 = "AGT", dna2 = "TGC"
  • 输出: 3
  • 解析:
    • 通过多次替换和删除操作,将AGT转换为TGC
    • 最少编辑步骤数为3。

样例4:

  • 输入: dna1 = "A", dna2 = "T"
  • 输出: 1
  • 解析:
    • A替换为T
    • 最少编辑步骤数为1。

解决方案

这是一个经典的**编辑距离(Levenshtein Distance)**问题。编辑距离是指将一个字符串转换为另一个字符串所需的最少编辑步骤数,编辑操作包括插入、删除和替换。

算法步骤:

  1. 动态规划:

    • 创建一个二维数组dp,其中dp[i][j]表示将dna1的前i个字符转换为dna2的前j个字符所需的最少编辑步骤数。
    • 初始化dp[0][0] = 0,表示空字符串转换为空字符串不需要任何步骤。
    • 初始化第一行和第一列,分别表示将空字符串转换为另一个字符串所需的操作数。
  2. 状态转移:

    • 如果dna1[i-1] == dna2[j-1],则dp[i][j] = dp[i-1][j-1]
    • 否则,dp[i][j] = 1 + min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]),分别对应删除、插入和替换操作。
  3. 最终结果:

    • dp[m][n]即为最终结果,其中mn分别是dna1dna2的长度。

代码解析

代码概述

你提供的代码是一个Java程序,旨在计算一个整数N的二进制反码,并将其转换回十进制数。代码还包含了一些测试用例,用于验证函数的正确性。

代码细节

public class Main {
    public static int solution(int N) {
        // 处理特殊情况 N = 0
        if (N == 0) {
            return 1;
        }

        // 将 N 转换为二进制字符串
        String binaryStr = Integer.toBinaryString(N);

        // 计算二进制反码
        StringBuilder reversedBinary = new StringBuilder();
        for (char c : binaryStr.toCharArray()) {
            // 将 '1' 变为 '0','0' 变为 '1'
            reversedBinary.append(c == '1' ? '0' : '1');
        }

        // 将反码转换回十进制数
        int result = Integer.parseInt(reversedBinary.toString(), 2);

        return result;
    }

    public static void main(String[] args) {
        System.out.println(solution(5) == 2 ? 1 : 0);
        System.out.println(solution(10) == 5 ? 1 : 0);
        System.out.println(solution(0) == 1 ? 1 : 0);
    }
}

代码解析

  1. 处理特殊情况:

    • 如果N为0,直接返回1,因为0的反码是1。
  2. 转换为二进制字符串:

    • 使用Integer.toBinaryString(N)将整数N转换为二进制字符串表示。
  3. 计算二进制反码:

    • 使用StringBuilder遍历二进制字符串,将每个字符'1'替换为'0',每个字符'0'替换为'1'
  4. 转换回十进制数:

    • 使用Integer.parseInt(reversedBinary.toString(), 2)将反码二进制字符串转换回十进制数。
  5. 测试用例:

    • solution(5)的预期输出为2,因为5的二进制是101,反码是010,转换为十进制是2。
    • solution(10)的预期输出为5,因为10的二进制是1010,反码是0101,转换为十进制是5。
    • solution(0)的预期输出为1,因为0的二进制是0,反码是1。

代码运行结果

运行上述代码,输出结果为:

1
1
1

这表明所有测试用例均通过,代码正确实现了计算二进制反码的功能。

改进建议

  • 输入验证: 可以添加输入验证,确保输入为非负整数。
  • 优化性能: 对于非常大的整数,可以考虑使用位运算来计算反码,而不是字符串操作,以提高性能。

示例运行

public class Main {
    public static int solution(int N) {
        if (N == 0) return 1;
        String binaryStr = Integer.toBinaryString(N);
        StringBuilder reversedBinary = new StringBuilder();
        for (char c : binaryStr.toCharArray()) {
            reversedBinary.append(c == '1' ? '0' : '1');
        }
        return Integer.parseInt(reversedBinary.toString(), 2);
    }

    public static void main(String[] args) {
        System.out.println(solution(5));  // 输出: 2
        System.out.println(solution(10)); // 输出: 5
        System.out.println(solution(0));  // 输出: 1
    }
}

运行结果:

2
5
1

总结

你提供的代码实现了计算一个整数的二进制反码的功能,并通过测试用例验证了其正确性。代码结构清晰,逻辑正确。如果需要处理更复杂的情况或优化性能,可以考虑上述建议。