算法设计与分析——蛮力法

前言

蛮力法感觉是在用最笨的方法解决问题,但是对一些问题不乏适用性。对于算法中的多种问题的求解我们大多时候还是会用其他算法技术,这里只是大概看看有哪些算法问题。

1.设计思想

蛮力法又叫枚举法或穷举法,基本技术是遍历,即按照某种策略依次处理待求解问题的所有元素,从而找出所有的元素。

2.查找问题中的蛮力法

2.1顺序查找

【问题】在查找集合中依次查找值为k的元素,若查找成功,则给出该元素在查找集合中的位置;若查找失败,则给出失败的信息。

【算法实现1】

int SeqSearch(int r[],int n,int k)
{
	int i=n-1;
	while(i>=0&&r[i]!=k)
		i--;
	return i;
 } 

【算法分析1】

基本语句:i>0和r[i]!=k

执行次数:2×1/n×(1+n)×n/2=n+1=O(n)

【算法实现2】设置一个哨兵

int SeqSearch(int r[],int n,int k)
{
	r[0]=k; //设置哨兵
	int i=n;
	while(r[i]!=k)i--;
	return i;
 } 

【算法分析2】

基本语句:r[i]!=k

执行次数:(n+1)/2=O(n)

2.2串匹配问题

【问题描述】给定两个字符串S和T,在主串S中查找子串T的过程称为串匹配,T称为模式。设主串S=“abcabcacb”,模式T=“abcac”

【算法实现】BF算法,即暴力算法

#include<iostream>
using namespace std;
int BF(char S[],char T[])
{
	int index=0;
	int n=0,m=0;
	while((S[n]!='\0') && (T[m]!='\0'))
		{
			if(S[n]==T[m])
			{
				n++;m++;
			}
			else
			{
				index++;n=index;m=0;	
			}
		}
	if(T[m]=='\0') return n+1;
	else return  0;
}
int main()
{
	char s[30];
	gets(s);
	char t[20];
	gets(t);
	cout<<BF(s,t);
}

【算法分析】假设在第i个位置匹配成功了,那么在前i-1趟中共比较了(i-1)×m次,第i趟比较了m次,所以总的比较了i×m次,时间复杂性是O(n×m)

【代码优化】KMP算法

首先计算模式串T的next数组,求解过程如下:

void GetNext(char T[],int next[])
{
	int i,j,len;
	next[0]=-1;
	for(i=1;T[i]!='\0';i++)
	{
		for(len=i-1;len>=1;len--)//相等子串的最大长度是j-1
		{
			for(j=0;j<len;j++)
			{
				if(T[j]!=T[i-len+j])break;//依次比较T[0]~T[len-1]和T[i-len]~T[i-1]
			}
			if(j==len)
			{
				next[i]=len;
				break;
			}
		}	
		if(len<1)next[i]=0;//没有相等的子串
	}
}

KMP算法:

int KMP(char S[],char T[])
{
	int i=0,j=0;
	int next[10]={-2};
	GetNext(T,next);
	while(S[i]!='\0'&& T[j]!='\0')
	{
		if(S[i]==T[j])
		{
			i++;
			j++;
		}
		else
		{
			j=next[j];
			if(j==-1)
			{
				i++;
				j++; 
			}
		}
	}
	if(T[j]=='\0')
	{
		return (i-strlen(T)+1);
	}
	else return 0;
}

主函数:

int main()
{
	cout<<"S:";
	char S[10];
	gets(S);
	cout<<"T:";
	char T[10];
	gets(T);
	cout<<KMP(S,T); 
}

【算法分析】在算出next数组后,KMP算法的时间复杂度是O(n)即把字符串T扫描了一下。而计算next值的时间代价最坏是O(_m{}^{3}

3.排序问题中的蛮力法

3.1选择排序

【问题描述】初始序列:49 27 65 76 38 13,按升序排序

【算法实现】

#include<iostream>
using namespace std;
void SelectSort(int a[],int n)
{
	int i,j,index,temp;
	for(i=0;i<n-1;i++)
	{
		index=i;
		for(j=i+1;j<n;j++)
		{
			if(a[j]<a[index])index=j; 
		}
		if(index!=i)
		{
			temp=a[i];a[i]=a[index];a[index]=temp;//不是a[i]=a[j]
		}
	}
	for(int i=0;i<n;i++)
	cout<<a[i]<<" ";
} 
int main()
{
	int a[6]={49,27,65,76,38,13};
	SelectSort(a,6);
	return 0; 
}

【算法分析】时间复杂性是O(_n{}^{2}

3.2起泡排序

【问题描述】起泡排序的基本实现是两两比较,如果反序就交换,直到没有反序的记录为止

就像冒泡一样,起泡越来越大。

【算法实现】

#include<iostream>
using namespace std;
void Bubblesort(int a[],int n)
{
	int bound=0;
	int exchange=n-1;//第一趟起泡排序的区间[0,n-1] 
	int i,temp;
	while(exchange!=0)
	{
		bound=exchange;
		exchange=0;
		for(i=0;i<bound;i++)//一趟起泡排序的区间是[0,bound] 
		{
			if(a[i]>a[i+1])
			{
				temp=a[i];a[i]=a[i+1];a[i+1]=temp;
				exchange=i;	//计录每一次交换的位置 
			}
		}
	}
	for(i=0;i<n;i++)
	 cout<<a[i]<<" "; 
}
int main()
{
	int a[8]={50,13,55,97,27,38,49,65};
	Bubblesort(a,8);
 } 

【算法分析】基本语句是a[i]>a[i+1],时间复杂度是O(_n{}^{2}

4.组合问题中蛮力法

4.1 0/1背包问题

十分经典的题目,后面用其他算法技术解决。

【问题解决】

对集合中的每个子集计算价值,取得到最大价值的那个子集。

【算法分析】对于有N个元素的集合,其子集数量是_2{}^{n},复杂性下界是Ω(_2{}^{n}

4.2 任务分配问题

也是一道很经典的题目

【问题描述】假设有n个任务需要分配给n个人执行,每个任务只能分配给一个人,每个人只执行一个任务,且第i个人执行第j个任务的成本是_C{ij}(1<=i,j<=n),任务分配问题要求找出总成本最小的分配方案。

【问题解决】对集合的全排列进行考察

【算法分析】全排列数量是n!,所以时间下界是Ω(n!)

5.图问题中的蛮力法

5.1哈密顿回路问题

【问题描述】哈密顿回路问题要求从一个城市出发,经过每个城市恰好一次,然后回到出发城市。

【问题解决】对结合{1,2,3,4,5}进行全排列,依序对排列进行判断是否是回路,是的话结束,不是的继续考察下一个排列。

【算法分析】最坏的情况下要考察顶点集合的所有全排列

5.2TSP问题

【问题描述】TSP问题是指旅行家要旅行N个城市然后回到出发城市,要求各个城市经历仅经历一次,并要求所走的的路程最短。

【问题解决】找出所有可能的旅游路线,即依次考察图中所有顶点的全排列,从中选取路径长度最短的哈密顿回路

【算法分析】必须依次考察顶点集合的所有全排列,从中找出路径最短的简单回路,时间下界是

Ω(n!)

6.几何问题中的蛮力法

【问题描述】要求在一个包含n个点的集合中找出距离最近的两个点。

【问题解决】分别计算每一对点之间的距离,然后找出距离最小的那一对。

【算法分析】时间复杂度是O(_n{}^{2}

  • 26
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值