算法分析與設計筆記(一)


復雜度分析

  • 低階函數

  • 同階函數

  • 高階函數

  • 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去掉最后一位的每個字符計算偏移表,其他字符直接移動整個字符串長度
  • 算法描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM