LeetCode Week10: Edit Distance, Unique Binary Search Tree(I & II)

这一周完成的主要是动态规划的题目,这里选择Edit Distance 和Unique Binary Search Tree(I & II)来分享题解。

一、Edit Distance

题目

Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)

You have the following 3 operations permitted on a word:

a) Insert a character
b) Delete a character
c) Replace a character

我的分析

对于两个字符串进行最少次数的三种修改使得两个字符串相等是动态规划中的经典题目,其本质可以看做是一个数组填充过程,数组的大小为editdis[len1+1][len2+1],其中len1和len2分别是两个字符串的长度,数组表示对于长度为len1和len2的两个字符串的最小的edit distance。下面以sunny和sandy为例,说明整个过程。
这里写图片描述

下面对整个图进行分析,对应图上的标注:

  1. 在每一个字符串前加入了新的行或列,标注①表示如果串2为空时,要给串2加入元素到和串1相等时需要的最小edit distance;标注②表示如果串1为空时的对应不同长度的串2的最小edit distance。标注①和标注②的交集处元素表示两个串都是空时的最小edit distance,即为0(不需要修改)

  2. 对于从左往右的填充一行元素,表示从当前元素开始,对于串2,需要添加多少个元素才能与串1相等。比如标注③,当前串1和串2都有元素s,所以不需要修改,如果继续遍历串1的后续元素,那么就要不停的给串2添加元素才能与串1相等(也可以考虑是对于串1,需要删除几个元素才能与串2相等);

  3. 对于从上往下的填充一列元素,表示从当前元素开始,对于串1,需要添加多少个元素才能与串2相等。比如标注③,当前串1和串2都有元素s,所以不需要修改,如果继续遍历串2的后续元素,那么就要不停的给串1添加元素才能与串2相等(也可以考虑是对于串2,需要删除几个元素才能与串1相等);

  4. 对于沿对角线方向填充数组,是表示当前两个串的长度是相等的,看要修改多少个元素才能使得两个串相等。比如对于串1和串2,都遍历到了相同的元素s,这相对于两个串都是空时的遍历而言,新添加的元素不需要修改,所以还是0,而接下来两个字符串都遍历一个新元素,一个是遍历到了’u’,一个是遍历到了’a’,这两个元素是不相同的,那么就要修改u或者是a,使得两个相等长度的字符串可以变得相同;

  5. 在三种填充中,选择可以有最小edit distance的值放入到数组对应位置中。

代码

二、Unique Binary Search Tree(I & II)

题目

Given an integer n, generate all structurally unique BST’s (binary search trees) that store values 1…n.

For example,
Given n = 3, your program should return all 5 unique BST’s shown below.

1         3     3      2      1
 \       /     /      / \      \
  3     2     1      1   3      2
 /     /       \                 \    
2     1         2                 3

我的分析

这个题是要求在给定的数目序列中,可以形成多少种BST,简单版是求多少种,进阶版是求具体的树的构造情况,考虑在长度为n的序列中,我们随机挑选一个元素i为根结点元素,那么剩下的n-1个元素可以被随机划分为两堆,一堆是大于i的元素,而另一堆的元素都小于i。那么对于元素i,以它为根结点的BST的构造情况,就是把上述两堆分别构造为子树时的可能数目的累乘(因为每一种左子树都可以与任意一种符合条件的右子树搭配)。

故对于简单版,假设num[i] 表示长度为i的元素序列的BST情况数,那么对于从1~i的数中,我们重复i次,每次挑选一个元素作为根,然后剩下的元素构造两颗子树,将得到的子树数目相乘,最终将i次的结果累加,就是num[i] 的值。

而对于进阶版,同样需要重复i次的挑选一个元素做根另外的元素构造子树,但是需要把每一次的子树情况存放起来,之后根据找到的子树的情况,每一次提取一个左子树和右子树,与当前的根结点结合,形成一棵完整的树后存放到vector中。—— 假设我们把构造子树的元素的位置定义为begin~end,那么对于begin的元素

  • begin > end:不存在这样的元素,也就是说没有这样的子树,子树为NULL;
  • begin == end: 用一个元素构造子树,那么子树就是一个值为begin/end的结点;
  • begin < end:与上述步骤一致,重复end-begin+1次,每次挑选其中的一个元素做根,然后构造左右子树,左右子树的情况分别为k和z种,那就做k*z种不同情况的结合得到最终的完整的BST。

代码

Unique Binary Search Tree I 的代码情况如下:

class Solution {  
public:  
    int numTrees(int n) {  
        int num[n+1] = {0};
        num[0] = 1; num[1] = 1;
        for(int i=2; i<=n; i++){
            for(int j=0; j<i; j++)  
                // 等于左子树的可能情况数乘以右子树的可能情况数 
                num[i]+=num[j]*num[i-j-1]; 
        } 
        return num[n];  
    }  
};  

Unique Binary Search Tree II 的代码情况如下:

class Solution {
public:
    vector<TreeNode*> generateTrees(int n) {
        vector<TreeNode *>res;
        if(n == 0) return res;
        res = Helper(1, n);
        return res;
    }
    vector<TreeNode*> generate(int begin, int end){
        vector<TreeNode*> node;

        if(begin > end) node.push_back(NULL); // 不会创建子树,故子树为NULL 
        else if(begin == end) node.push_back(new TreeNode(end)); // 只有一个数,所以创建一个新结点 
        else{
            for(int i = begin; i <= end; i++){
                // 生成左子树和右子树 
                vector<TreeNode*> lroot = generate(begin,i-1);
                vector<TreeNode*> rroot = generate(i+1,end);
                for(int k = 0; k < lroot.size(); k++)
                    for(int z = 0; z < rroot.size(); z++){   
                    // 每一种左子树都可以跟每一种右子树有一种组合                
                        TreeNode *root = new TreeNode(i);
                        root->left = lroot[k];
                        root->right = rroot[z];
                        node.push_back(root);
                }

            }
        }
        return node;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值