算法小结 之 蛮力法

文章目录

    • 1.1 蛮力法的定义
    • 1.2 蛮力法的优缺点
    • 1.3 蛮力法的设计思想
    • 1.4 蛮力法的经典使用
      • 1.4.1 排序
        • 1.4.1.1选择排序
        • 1.4.1.2冒泡排序
      • 1.4.1.3 顺序查找
      • 1.4.2 字符串匹配问题
      • 1.4.3 最近点对的蛮力算法
      • 1.4.4 凸包问题的蛮力算法
      • 1.4.5 穷举法
        • 1.4.5.1 NP难问题
          • 1.4.5.2 TSP问题
          • 1.4.5.3 背包问题
        • 1.4.5.4 分配问题

1.1 蛮力法的定义

 蛮力法又称为枚举法,穷举法,暴力法。蛮力算法是一种简单直接地解决问题,但不一定是最高效的方法


1.2 蛮力法的优缺点

蛮力法所具有的优点:

  1. 应用范围广,不受实列规模的限制
  2. 当要解决的问题低频率出现,并且高效算法很难设计时可选用蛮力法
  3. 对解决一些小规模的问题实列仍然有效
  4. 可作为衡量其他算法的参照物

蛮力法所具有的缺点:

  1. 用蛮力法设计的算法其时间性能往往也是最低的, 典型的指数时间算法一般都是通过蛮力搜索而得到的

1.3 蛮力法的设计思想

蛮力法是指采用遍历(扫描)技术,即采用一定的策略将待求解问题的所有元素依次处理一次,从而找出问题的解。依次处理所有元素是蛮力法的关键,为了避免陷入重复试探,应保证处理过的元素不再被处理。


1.4 蛮力法的经典使用

1.4.1 排序

1.4.1.1选择排序

问题描述:

​ 给定一个可排序的n元序列,将它们按照非降序方法重新排序

使用蛮力法的思路(递归描述):

  1. 扫描整个列表,找出n个元素中最小的元素,将其置于末端
  2. 对剩余的n-1个元素执行步骤一
  3. 当所剩元素为1时,停止操作

算法设计(伪代码):

//非递归
Algorithm SS(A[0..n-1]) //SelectionSort
    //输入:n元数组
    //输出:n元数组
    for i=0 to n-2 do
        min:=i;
		for j:=i+1 to n-1 do
            if A[j]<A[min] then min->j;
		swap A[i] and A[min]

算法分析:

  • 输入规模(空间复杂度)

    因为输入的是n元数组,故空间复杂度是:O(n)

  • 算法的基本操作:

    比较A[j] < A[min],数据交换swap

  • 比较次数C(n)
    C ( n ) = ∑ i = 0 n − 2 ∑ j = i + 1 n − 1 1 = ∑ i = 0 n − 2 ( n − 1 − i ) = n ( n − 1 ) 2 C(n)={\sum_{i=0}^{n-2}\sum_{j=i+1}^{n-1}1}={\sum_{i=0}^{n-2}(n-1-i)}=\frac{n(n-1)}{2} C(n)=i=0n2j=i+1n11=i=0n2(n1i)=2n(n1)
    于是C(n)属于O(n2)


1.4.1.2冒泡排序

问题描述:

​ 给定一个可排序的n元序列,将它们按照非降序方法重新排序

使用蛮力法的解决思路:

  1. 比较相邻的元素,将大的元素交换到右边的位置,重复多次后,最大的元素交换到最右边
  2. 第二遍将第二大的元素沉下去,n-1次后结束

算法设计:

Algorithm BS(A[0..n-1]) //BubbleSort
    //输入:n元数组
    //输出:n元数组
    for i:=0 to n-2 do
    	for j:=0 to n-2-i do
        	if A[j+1]<A[j] then swap A[j] and A[j+1]

算法分析:

  • 输入规模(空间复杂度)

    因为输入的是n元数组,故空间复杂度是:O(n)

  • 算法的基本操作:

    比较A[j] < A[j+1],数据交换swap

  • 比较次数C(n)
    C ( n ) = ∑ i = 0 n − 2 ∑ j = 0 n − 2 − i 1 = ∑ i = 0 n − 2 ( n − 1 − i ) = n ( n − 1 ) 2 C(n)={\sum_{i=0}^{n-2}\sum_{j=0}^{n-2-i}1}={\sum_{i=0}^{n-2}(n-1-i)}=\frac{n(n-1)}{2} C(n)=i=0n2j=0n2i1=i=0n2(n1i)=2n(n1)
    于是C(n)属于O(n2)


1.4.1.3 顺序查找

问题描述:

​ 已知有n个元素的数组A[0…n],给定元素K,要求找出一个下标i,,使得A[i]=K.。输出第一个值等于K的元素的位置,找不到返回-1。

使用蛮力法解决问题的思路:

​ 遍历数组

算法设计:

Algorithm SequentialSearch(A[0..n-1],K)
    //输入:n元数组,给定元素k
    //输出:所寻找到的元素k的下标
    i:=0;
    while A[i]≠K and i<n do   
        i:=i+1; 
	if A[i]=K  then return i
        else return -1

算法分析:

  • 输入规模

    因为输入的是n元数组,故空间复杂度是:O(n)

  • 算法的基本操作

    比较A[i]与k是否相同

  • 比较次数

    • 最坏情况:n
    • 最好情况:1

1.4.2 字符串匹配问题

问题描述:

​ 从文本中寻找匹配模式的子串,即求出第一个匹配模式的子串在文本中的开始位置(子串最左元素的下标)。

使用蛮力法解决问题的思路:

​ 将模式对准文本的前m个字符从左往右进行比对,如果其中有一个字符不匹配,模式往右移动一位继续下一个m个字符的比对。

算法小结 之 蛮力法_第1张图片

算法设计:

Algorithm BFSM (T[0..n-1], P[0..m-1])// Brute Force String Match
   //输入:文本数组T[0..n-1],模式数组P[0..m-1]  (n>m)
   //输出:所寻找的的位置的下标,查找不成功时返回-1
    for i :=0 to n-m do
        j := 0
        while j<m and P[j]=T[i+j] do
        	j :=  j+1
            if j=m return i
     return -1

算法分析:

  • 输入规模

    输入了两个数组,长度分别为n和m,故空间复杂度是:O(n+m)

  • 算法的基本操作

    比较

  • 比较次数

    • 最坏情况:

      模式需要移动n-m+1次,模块每次移动前,都要做m次对比,此时的时间复杂度属于nm级别

    • 最好情况:

      模式不需要移动,只需要比较m次,时间复杂度属于m级别

    • 平均时间复杂度属于n级别的


1.4.3 最近点对的蛮力算法

问题描述:

​ 给定平面S上n个点,找其中的一对点,使得在n(n-1)/2个点对中,该点对的距离最小。

使用蛮力法解决问题的思路:

​ 把所有的点两两组合,比较它们之间的距离即可以得到距离最小的一对

算法设计:

Algorithm BFCP ( P )  // Brute Force Closest Points
    // 输入:n个点的数组P,Pi(xi , yi), i=1, 2, …, n
    // 输出:两个最近点的下标index1和index2
    dmin :=;
    for i := 1 to n-1 do
        for j := i+1 to n  do
            d := sqrt((xi-xj)2+(yi-yj)2);
    if d < dmin then
        dmin := d;
    index1 := i;   index2 := j;
    return index1, index2

算法分析:

  • 输入规模

  • 算法的基本操作

    平方操作

  • 比较次数C(n)
    C ( n ) = ∑ i = 1 n − 1 ∑ j = i + 1 n 2 = 2 ∑ i = 0 n − 2 ( n − i ) = n ( n − 1 ) C(n)={\sum_{i=1}^{n-1}\sum_{j=i+1}^{n}2}=2{\sum_{i=0}^{n-2}(n-i)}=n(n-1) C(n)=i=1n1j=i+1n2=2i=0n2(ni)=n(n1)
    于是C(n)属于O(n2)


1.4.4 凸包问题的蛮力算法

问题描述:

凸集定义:

​ 设S是平面点集,如果S中任意两点的连线都属于该集合,则称S是凸的

凸包定义:

​ 一个点集S的凸包是指包含S的最小凸集。显然,如果S是凸的,则S的凸包就是S本身(橡皮筋圈解释)。

​ 给定一个n个点的点集S,求S的凸包。

使用蛮力法解决问题的思路:

极点:

​ 凸集的极点是指不会出现在集合中任何线段的中间的点。

​ 设点集大小为n,首先将其中的点两两配对,得到直线段条。

​ 然后对每一条直线段检查其余的n-2个点的相对于该直线段的正负性,如果它们都有相同的正负性,那么这条直线段属于凸多边形的边,其顶点是极点。


1.4.5 穷举法

穷举法是一种简单的蛮力方法,它要求生成所有可能的可行解,再从中选择最优解。


1.4.5.1 NP难问题

目前没有已知的效率可以用多项式来表示的算法,需要通过穷举法去解决,下面是两个经典问题:

1.4.5.2 TSP问题

给定n个城市相互之间的距离,求一条能走遍n个城市的最短路径,使我们能从任一城市开始,访问每个城市只一次后回到起点。


1.4.5.3 背包问题

给定n个重量为w1、w2…wn,价值为v1、v2、…、vn的物品和一个承重为W的背包,如何将物品装入背包使背包所获的价值最大。


1.4.5.4 分配问题

n个任务需要分配给n个人执行,一人一个任务。将第j个任务分配给第i个人的成本是C[i, j],求总成本最小的分配方案。

可用穷举法列出n的阶乘个可能的解决方案

你可能感兴趣的:(算法学习)