Leetcode Edit Distance

Leetcode Edit Distance,本题可以使用两种法方来完成,不过可能效率有所不一样。

动态规化

使用record[word1.length + 1][word2.length + 1] 记录值。
如果要计算word1[index1…end1], word2[index2…end2]的值,可以分成以下四种情况:
1. 如果word1[index1] == word2[index2],最优值为record[index1+1][index2+1]
2. 替换word1[index1]为word2[index2],此时最优值为record[index1 + 1][index2 + 1] + 1
3. 删除word1[index2],此时最优值为record[index1 + 1][index2] + 1
4. 在word1中插入一个与word2[index2]相等的值,此时最优值为record[index1][index2 + 1] + 1

相关代码如下:

#include<iostream>
#include<vector>
#include<string>

using namespace std;
/**
 * Using the dynamic programming algorithm.
 * Using a table record[len1 + 1][len2 + 2] to record the tmp result
 * and the record[0][0] will be the result
 */
class Solution {
public:
    int minDistance(string word1, string word2) {
        int len1 = word1.length();
        int len2 = word2.length();
        int minNum = len1 > len2? len1: len2;;
        int curNum = 0;
        vector<vector<int> > record = vector<vector<int> >(len1 + 1, vector<int>(len2 + 1, -1));
        recursiveMin(word1, 0, word2, 0, record);
        return record[0][0];
    }
    void recursiveMin(string& from, int fromIdx, string& to, int toIdx,
            vector<vector<int> >& record) {
        // if there is a record just return
        if (record[fromIdx][toIdx] != -1) {
            return;
        }
        // till the end of this turn, calculate the value and return
        if (fromIdx == from.length() || toIdx == to.length()) {
            record[fromIdx][toIdx] = (from.length() - fromIdx) + (to.length() - toIdx);
            return;
        }
        if (from[fromIdx] == to[toIdx]) {
            // this must be the optimal
            recursiveMin(from, fromIdx + 1, to, toIdx + 1, record);
            record[fromIdx][toIdx] = record[fromIdx + 1][toIdx + 1];
        } else {
            recursiveMin(from, fromIdx + 1, to, toIdx + 1, record);
            recursiveMin(from, fromIdx, to, toIdx + 1, record);
            recursiveMin(from, fromIdx + 1, to, toIdx, record);
            // get the minest of the three
            record[fromIdx][toIdx] = minOfThree(
                    record[fromIdx + 1][toIdx + 1],
                    record[fromIdx][toIdx + 1],
                    record[fromIdx + 1][toIdx]
                    ) + 1;
        }
    }
    int minOfThree(int a, int b, int c) {
        if (a > b) {
            return b < c? b : c;
        } else {
            return a < c? a : c;
        }
    }
};

int main(int argc, char* argv[]) {
    Solution so;
    cout<<"result: "<<so.minDistance(string(argv[1]), string(argv[2]))<<endl;
    return 0;
}
测试:
time ./a.out pneumonoultramicroscopicsilicovolcanoconiosis ultramicroscopically
result: 27

real    0m0.004s
user    0m0.001s
sys 0m0.002s
分支界限法

分支界限法主要情况与动态规划相似,主要不同的是,其不使用record数组来记录情况,而是记录一个当前最小值min,以及当前值cur,以及当前情况进行预估.
针对本问题的预估值为:word1和word2剩余长度较大者加上cur。并使用预估值做为剪支条件。

相关代码如下:

#include<iostream>
#include<vector>
#include<string>

using namespace std;
/**
 * Using branch-bound method
 * Each turn we get a espect max result, if the result greater than the current
 * result, just cut this branch
 */
class Solution {
public:
    int minDistance(string word1, string word2) {
        int len1 = word1.length();
        int len2 = word2.length();
        int minNum = len1 > len2? len1: len2;;
        int curNum = 0;
        recursiveMin(word1, 0, word2, 0, 0, minNum, len1, len2);
        return minNum;
    }
    void recursiveMin(string& from, int fromIdx, string& to, int toIdx,
            int curNum, int& minNum, int len1, int len2) {
        // leverage this branch
        if (curNum + (len1 - len2) >= minNum || curNum + (len2 - len1) > minNum) {
            return;
        }
        // an end
        if (fromIdx == from.length() || toIdx == to.length()) {
            curNum = curNum + (from.length() - fromIdx) + (to.length() - toIdx);
            minNum = curNum < minNum? curNum : minNum;
            return;
        }
        // get other condition
        if (from[fromIdx] == to[toIdx]) {
            recursiveMin(from, fromIdx + 1, to, toIdx + 1, curNum, minNum,
                    len1 - 1, len2 - 1);
        } else {
            recursiveMin(from, fromIdx + 1, to, toIdx + 1, curNum + 1, minNum,
                    len1 - 1, len2 - 1);
            recursiveMin(from, fromIdx, to, toIdx + 1, curNum + 1, minNum, len1, len2 - 1);
            recursiveMin(from, fromIdx + 1, to, toIdx, curNum + 1, minNum, len1 - 1, len2);
        }
    }
};

int main(int argc, char* argv[]) {
    Solution so;
    cout<<"result: "<<so.minDistance(string(argv[1]), string(argv[2]))<<endl;
    return 0;
}
测试:
time ./a.out pneumonoultramicroscopicsilicovolcanoconiosis ultramicroscopically
result: 27

real    0m0.007s
user    0m0.004s
sys 0m0.002s
总结

从以上运行情况也可以看出,动态规划的性能好于分支界限法,这与我在leetcode测试基本一致,动态规划为:24ms,分支界限法为:84ms。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值