笔试面试题目:编辑距离

      原文发表于:

      编辑距离,可以用于度量两个字符串的差异。其含义是:一个字符串到另一个字符串的最少变换次数,其中,变换操作仅涉及增删改,且每次只能操作一个字符。

      编辑距离的应用很广,比如纠错检错:

    

      编辑距离,在笔试面试中会经常涉及到。一朋友最近参加了T公司的面试,便遇到了编辑距离:

   

      编辑距离,是一个典型的动态规划问题。那么,从一个字符串到另一个字符串的编辑距离一定存在吗?这是必然的,暴力方法可以证明,不必赘述。

      记dp[i][j]为字符串A的前i个字符到字符串B的前j个字符的编辑距离,如果A或B为空串,那么i或j为0,因此i的区间为[0, lenA], j的区间为[0, lenB]. 接下来,我们推导动态规划方程。

       (1) 如果A[i]等于B[j], 那么此时便是躺赢的模式,即有:

dp[i][j] = dp[i-1][j-1]

       (2) 如果A[i]不等于B[j], 则可以进行三种操作(增删改),如下:

        a. 把A的前i-1个字符变成B的前j个字符,然后删除一个字符;

        b. 把A的前i个字符变成B的前j-1个字符,然后增加一个字符;

        c. 把A的前i-1个字符变成B的前j-1个字符,然后改变一个字符;

        显然,此时的动态规划方程为:

        dp[i][j] = 1 + min{dp[i-1][j],dp[i][j-1],dp[i-1][j-1]}

        

       算法搞懂后,程序就简单了:​​​​​​

func minDistance(A string, B string) int {
    lenA := len(A)
    lenB := len(B)

    // 初始化二维slice
    dp := make([][]int, lenA + 1)
    for i := 0; i < lenA + 1; i++ {
        dp[i] = make([]int, lenB + 1)
    }

    for i := 0; i < lenA + 1; i++ {
        dp[i][0] = i
    }

    for j := 0; j < lenB + 1; j++ {
        dp[0][j] = j
    }

    for i := 1; i < lenA + 1; i++ {
        for j := 1; j < lenB + 1; j++ {
            if A[i - 1] == B[j - 1] {
                dp[i][j] = dp[i-1][j-1]
            }else {
                dp[i][j] = 1 + min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1])
            }
        }
    }

    return dp[lenA][lenB]
}

func min(x, y, z int) int {
    m := x
    if x > y {
        m = y
    }

    if m > z {
        m = z
    }

    return m
}

       在leetcode上测试,通过。

       周末愉快,祝应届毕业生和社招的朋友拿到更好的offer.

猜你喜欢

转载自blog.csdn.net/stpeace/article/details/110419493