zoukankan      html  css  js  c++  java
  • 算法分析与设计笔记(一)

    复杂度分析

    • 低阶函数

    • 同阶函数

    • 高阶函数

    • master定理求解阶数/迭代法求解具体的

    递归方程

    • 整数划分问题
    将正整数n表示成一系列正整数之和,n=n1+n2+n3+......nk(其中,n1>=n2>=......nk>=1,k>=1),正整数n的这种表示称为正整数n的划分。正整数n的不同划分个数称为正整数n的划分数,记作p(n)。例如:正整数6有11总不同的划分
    
    6;
    
    5+1;
    
    4+2,4+1+1;
    
    3+3,3+2+1,3+1+1+1;
    
    2+2+2,2+2+1+1,2+1+1+1+1;
    
    1+1+1+1+1+1;
    
    记q(n,m)为正整数n的所有不同划分中,最大加数n1不大于m的划分个数。可以建立如下递推关系:
    
    前面三个递推式比较好理解,关键是第四个递推式。当n>m>1时,n的划分由两部分组成。以整数q(6,3)为例,q(n,m-1)内容是第5排和第6排内容,不大于2的6的划分;q(n-m,m)内容是第4排,不大于3的(6-3=3)的划分。
    
    
    //2-4 整数划分问题  
    #include "stdafx.h"  
    #include <iostream>       
    using namespace std;  
      
    int q(int n,int m);  
      
    int main(){  
        cout<<q(6,6)<<endl;  
        return 0;  
    }  
      
    int q(int n,int m)  
    {  
        if( n<1 || m<1)  
        {  
            return 0;  
        }  
        else if(n==1 || m==1)  
        {  
            return 1;  
        }  
        else if(n<m)  
        {  
            return q(n,n);  
        }  
        else if(n==m)  
        {  
            return q(n,m-1) + 1;  
        }  
        else  
        {  
            return q(n,m-1) + q(n-m,m);  
        }  
    }  
    
    • 汉诺塔问题
    • 古代有一个梵塔,塔内有三个座A、B、C,A座上有64个盘子,盘子大小不等,大的在下,小的在上。有一个和尚想把这64个盘子从A座移到B座,但每次只能允许移动一个盘子,并且在移动过程中,3个座上的盘子始终保持大盘在下,小盘在上。在移动过程中可以利用B座,要求输出移动的步骤。

    #include <iostream>       
    using namespace std;
    
    void hanoi(int n, char a, char b, char c);
    
    int main(){
    	char a = 'A', b = 'B', c = 'C';
    	hanoi(3, a, b, c);
    	return 0;
    }
    
    //借助c,将n个盘子从a移到b  
    void hanoi(int n, char a, char b, char c)
    {
    	if (n > 0)  //n等于1直接输出
    	{
    		hanoi(n - 1, a, c, b);//借助b,将n-1个盘子从a移到c  
    		cout << "将" << a << "中最大的盘子从" << a << "移到" << b << endl;
    		hanoi(n - 1, c, b, a);//借助a,将n-1个盘子从c移到b  
    	}
    }
    
    

    分治法

    • 设计过程分三阶段:划分,求解,合并
    • 自顶向下
      • 大整数(二进制)乘法
      • 最大值最小值问题(类似归并算法)
      • 中位数问题
      • 从n个不同的数中选第i大的元素(线性时间)
      • 快速傅里叶变换

    动态规划

    • 子问题相互独立,若不是相互独立,分治方法将重复计算公共子问题,效率低

    • 自底向上

    • 一类优化问题

    • 使用动态规划的条件:优化子结构,重叠子问题

    • 矩阵的乘法

    • 0-1背包问题

    • 动态规划方法可用的条件
      - 优化子结构
      - 子问题重叠性
      - 子问题空间小

    贪心法

    • 求解最优化问题

    • 每一步都有一组选择,作出在当前看来最好的选择

    • 希望通过作出局部优化选择达到全局优化选择

    • 贪心算法不一定总产生优化解

    • 贪心算法是否产生优化解,需要严格证明

    • 贪心算法产生优化解的条件是:
      - 贪心选择性
      - 优化子结构(严格)

    • 任务安排问题

    • 哈夫曼编码问题(前缀码-最优二叉树)

    搜索策略

    • 暴力美学

      • 转换为树搜索问题
    • 深度优先和广度优先

      • 广度优先-队列实现
      • 深度优先-栈实现
    • 搜索的优化

      • 爬山法(使用贪心方法确定搜索的方向)-局部优化
      • Best-First搜索策略-全局优化-用堆实现
      • 分支界限(可以有效地求解组合优化问题)(剪枝)-缩小解空间,加速搜索
    • 八数码难题(8 puzzle)(广度优先)

    • 求解子集和问题(深度优先)

    • 哈密顿(Hamiltonian)环问题(深度优先)

    字符串搜索

    • 字符串匹配问题

      • 计算匹配算法的复杂度O(m*(n-m))
    • Rabin-Karp算法,指纹思路。如果两个字符串hash后的值不相同,则它们肯定不相同;如果它们hash后的值相同,它们不一定相同。

    • RK算法的基本思想就是:将模式串P的hash值跟主串S中的每一个长度为|P|的子串的hash值比较。如果不同,则它们肯定不相等;如果相同,则再诸位比较之。

    • 参考:串的模式匹配算法---RK,Rabin-Karp指纹字符串查找算法

    • 补充Horner算法

    KMP算法

    • 利用已有部分匹配中的信息

    • 需要寻找overlap

    • 基于自动机的算法;

    • 前缀表,由于sigma有可能比较大,所欲忘记未匹配的字符(alfa)

    • 这样可能导致再次匹配失败,但是也只是多匹配了一次,这样换取了时间和空间的优化

    • P的前缀和P的前q位的后缀求最大的overlap,q+1位匹配失败

    • 核心就是求前缀表

    • KMP算法流程

    BMH算法

    • 用逆向简单算法中增加了启发式规则
    • P从前往后走,但模式P匹配时从后往前匹配
    • 真实应用中,不匹配的概率大,最坏也可能是O(n*m)

    • 对P去掉最后一位的每个字符计算偏移表,其他字符直接移动整个字符串长度
    • 算法描述

  • 相关阅读:
    缓冲区
    4.9
    JDBC连接
    3.31
    BizTalk框架概述
    不通过SPS对象模型更改文档扩展字段的方法
    asdfasdf
    设计模式介绍
    Multiple Checkbox Items In A DataGrid Introduction
    Factory Method
  • 原文地址:https://www.cnblogs.com/ranjiewen/p/6986332.html
Copyright © 2011-2022 走看看