zoukankan      html  css  js  c++  java
  • 动态规划-练习

    动态规划范式

    var catch = [[],[]];

    function someObscureFunction(a,b){

      if(...) return ...;//先处理初始部分

      var ret = catch[a][b];

      if(ret) return ret

      return catch[a][b] = 求解

    }

    练习1 通配符

      *  长度大于等于0的字符串

      ?   任一字符串

    例如:

      he?p 匹配 help,heap,无法匹配helpp.

      *p* 匹配papa

    代码如下,这个算法的复杂度为O(n*n*n),n<=100 可以接受。

    <script>
    function matchMemozied(W1,S1){
        var cache = [];
        var W = W1.split(''),S = S1.split('');
        function match(w,s){
            var w1 = w,s1=s,ret;
            if(cache[w1]){
                if(cache[w1][s1]){
                    return cache[w1][s1];
                }
            }else{
                cache[w1] = [];
            }
            while(s<S.length && w< W.length && (W[w] == '?' || W[w] == S[s]))
            {
                ++w;
                ++s;
            }
            if(w == W.length )
            return cache[w1][s1] = s==S.length;
            if(W[w] == '*')
             {  for(var i=0;i+s<=S.length;i++){
                    if(match(w1+1,s+i)){
                        return cache[w1][s1] = 1;
                    }
                }
             }
             return cache[w1][s1] = 0;
        }
        if(match(0,0)){
            console.log(S1);
        }
    }
    matchMemozied('he?p','heap');
    matchMemozied('he?p','heapp');
    matchMemozied('*p*','papa');
    </script>

    代码二,O(n*n)

    <script>
    
    function matchMemozied(W1,S1){
        var cache = [];
        var W = W1.split(''),S = S1.split('');
        function match(w,s){
            var w1 = w,s1=s,ret;
            if(cache[w1]){
                if(cache[w1][s1]){
                    return cache[w1][s1];
                }
            }else{
                cache[w1] = [];
            }
            if(s<S.length && w< W.length && (W[w] == '?' || W[w] == S[s]))
            {
                return cache[w1][s1] = match(w+1,s+1);
            }
            if(w == W.length )
            return cache[w1][s1] = s==S.length;
            if(W[w] == '*')
             {
                if(match(w+1,s) || (s<S.length && match(w,s+1)))
                {
                    return cache[w1][s1] = 1;
                }
             }
             return cache[w1][s1] = 0;
        }
        if(match(0,0)){
            console.log(S1);
            console.log(cache);
        }
    }
    matchMemozied('he?p','heap');
    matchMemozied('he?p','heapp');
    matchMemozied('*p*','papa');
    </script>

     典型优化问题

      优化问题就是在多个答案中选择出最佳答案(最优解),动态规划法起初是从快速解决优化问题

      利用动态规划法解题也是从穷举搜索法开始的

    练习:三角形的最大路径问题

      6

      1  2

      3  7  4

      9  4  1  7

      2  7  5  9  4

    从6开始往下走,只能向下和右下走(此时不计算向右走的一步的所在的数字),最终到达底部,找出数值之和最大的路径。

    首先用穷举搜索法

    <script>
    var data = [[6],
                [4,5],
                [7,1,6],
                [3,5,5,2],
                [9,1,3,6,2]];
     function path1(y,x,sum){
        if(y == data.length - 1){
            return sum + data[y][x];
        }
        return  Math.max(path1(y+1,x,sum+data[y][x]),path1(y+1,x+1,sum+data[y][x]));
     }
    var max = path1(0,0,0); 
    console.log(max);
    </script>

     这个事枚举所有的,文章还提到另一种思路,找最优子结构

    <script>
    var j=0;
    function path2(y,x){
        j++;
        if(y === data.length -1){
            return data[y][x];
        }
        return Math.max(path2(y+1,x),path2(y+1,x+1)) + data[y][x];
    }
    console.time('path2');
    var max2 = path2(0,0,0); 
    console.timeEnd('path2');
    console.log('max2:' + max);
    console.log('j:' + j);
    </script>

    这两个方法都跑了2的n次方,现在加入动态规划范式,第一种解法加范式的话需要三维数组,而且实际上没有节省执行次数,所以就没试,下一题就涉及到修改输入值来方便动态规划。

    <script>
    var k=0,cache =[];
    for(var m = 0;m< data.length;m++){
        cache[m] = [];
    }
    function path3(y,x){
        k++;
        if(y === data.length -1){
            return data[y][x];
        }
        if(cache[y][x]){
            return cache[y][x];
        }else{
            return cache[y][x] = Math.max(path3(y+1,x),path3(y+1,x+1)) + data[y][x];
        }
        
    }
    console.time('path3');
    var max3 = path3(0,0,0); 
    console.timeEnd('path3');
    console.log('max3:' + max);
    console.log('k:' + jk);
    </script>

    从结果上看,执行次数明显减少,结果也是相同的,但是执行时间略有增加。。。下一题,呜呜

     最长递增子序列问题

      比如 1,2,4 是 1,5,2,4,7 的递增子序列

      先上枚举搜索算法

    <script>
    function list(A){
        var ret = 0;
        for(var i = 0;i<A.length;i++){
            var B = [];
            for(var j = i+1 ; j<A.length;j++){
                if(A[i]<A[j]){
                    B.push(A[j]);
                }
            }
            ret = Math.max(ret,1 + list(B));
        }
        return ret;
    }
    var c = 100,data =[];
    while(--c>0){
        data.push(Math.floor(Math.random()*20))
    }
    console.log(data);
    console.time('list');
    var result = list(data);
    console.timeEnd('list');
    console.log(result);
    </script>

    现在的输入是数组,不适合缓存定位,现改为数组的下标作为参数

    <script>
    function list1(start){
        var ret = 1;
        for(var i = start+1;i<data.length;i++){
            if(data[start]<data[i]){
                ret = Math.max(ret,1 + list1(i));
            }
            
        }
        return ret;
    }
    console.time('list1');
    var result = list1(0);
    console.timeEnd('list1');
    console.log(result);
    </script>

    现在加入动态规划,就是缓存啦

    <script>
    function list2(start){
        if(cache[start +1 ]){
            return cache[start + 1 ];
        }
        cache[start + 1 ] = 1;
        for(var i = start+1;i<data.length;i++){
            if(start == -1 || data[start]<data[i]){
                cache[start + 1 ] = Math.max(cache[start + 1 ],1 + list2(i));
            }
            
        }
        return cache[start + 1 ];
    }
    var cache = [],max=0;
    console.time('list2');
     
    for(var k = 0;k<data.length;k++){
        max = Math.max(max,list2(k));
    }
    console.timeEnd('list2');
    console.log(max);
    </script>

    总得时间复杂度还是n*n 的,还有更少的,n*logn 

  • 相关阅读:
    Entity SQL 初入
    ObjectQuery查询及方法
    Entity Framework 的事务 DbTransaction
    Construct Binary Tree from Preorder and Inorder Traversal
    Reverse Linked List
    Best Time to Buy and Sell Stock
    Remove Duplicates from Sorted Array II
    Reverse Integer
    Implement Stack using Queues
    C++中const限定符的应用
  • 原文地址:https://www.cnblogs.com/poorpeople/p/7238233.html
Copyright © 2011-2022 走看看