深入浅出讲算法思想--蛮力法思想分析及应用

蛮力法(brute force method,也称为穷举法或枚举法)是一种简单直接地解决问题的方法,常常直接基于问题的描述,所以,蛮力法也是最容易应用的方法。虽然,用蛮力法设计的算法时间特性往往也是最低的,但是许多问题我们一开始并没有很优化的算法,而蛮力法则可以帮助我们从低效的算法结构中剖析低效的缘由,进而提炼出更为优化的算法。

  1. 蛮力法在排序算法中的应用(选择,冒泡)
  2. 蛮力法在查找算法中的应用
  3. 蛮力法在字符串匹配问题中的应用
  4. 蛮力法在求解“最近对”问题中的应用
  5. 蛮力法在求解凸包问题中的应用
  6. 蛮力法在求解最优解问题中的应用(TSP,背包问题,配对问题)

一、蛮力法在排序算法中的应用

对于一个排序问题,我们能想到的最简单的排序方法就是选择和冒泡

1、选择排序:时间复杂度O(n^2)

public class Main {public static void main(String[] args) {int[] a = {89, 45, 68, 90, 29, 34, 17};int min;for (int i = 0; i < a.length-1; i++) {min = i;for (int j = i+1; j < a.length; j++) {if (a[j] < a[min]) {min = j;}}int temp = a[i];a[i] = a[min];a[min] = temp;}for (int i = 0; i < a.length; i++) {System.out.print(a[i] + " ");}}
}

选择排序的思路就是如此,虽也有优化思路,例如每次迭代出最大值和最小值,放在开头和结尾。但是选择排序必然要编译算真整个数组,所以最好的优化结果也是O(n^2)。

2、冒泡排序时间复杂度O(n^2)

public class Main {public static void main(String[] args) {int[] a = {89, 45, 68, 90, 29, 34, 17};int min;for (int i = 0; i < a.length-1; i++) {for (int j = 0; j < a.length-1-i; j++) {if (a[j+1] < a[j]) {int temp = a[j];a[j] = a[j+1];a[j+1] = temp;}}}for (int i = 0; i < a.length; i++) {System.out.print(a[i] + " ");}}
}
发现问题:对于冒泡排序我们都知道,即使已经排好顺序,循环还是会继续进行,即使只比较不交换。

优化思路:当判断到数组已经不再发生改变之后就终止循环。

当然,这就是蛮力法的一个应用,通过蛮力的解法来找到优化的思路


二、蛮力法在查找算法中的应用

对于查找算法来说,最简单的一个思路就是逐个匹配,直到找到目标元素

顺序查找:

public class Main {public static void main(String[] args) {int[] a = {89, 45, 68, 90, 29, 34, 17, 0};int k = 45;int i = 0;a[a.length-1] = k;while (a[i] != k) {i++;}if (i < a.length-1) {System.out.println(i);} else {System.out.println("no find");}}
}
上面的算法不同于大家常见的算法,这是在顺序查找时常用的一个小技巧:将查找建添加到列表末尾(也称 限位器 ),那么查找必定会成功,这样就不比在每次循环都检查是否达到的末尾,只需再循环外面做一次即可。

发现问题:如果未定的数组是有序的,即使后面的元素都不可能等于查找建,但是算法不会停止

优化思路:当我们当查到一个比查找键还大的元素,仍未找到,那么就可以终止循环了。

三、蛮力法在字符串匹配问题中的应用
字符串匹配问题通常是给定一个n个字符组成的串(称为文本),一个m(m<=n)个字符的串(称为模式),从文本中寻找匹配模式的子串。显然我们需要逐个匹配,这是蛮力算法的典型特点。

蛮力匹配:时间复杂度O(n^2)

public class Main {public static void main(String[] args) {String[] a = {"a","b","c","d","e","f","g","h"};String[] b = {"e","f"};int flag = 0;for (int i = 0; i < a.length-b.length; i++) {int j = 0;while (j < b.length && b[j] == a[i+j]) {j = j+1;if (j == b.length-1) {flag = 1;System.out.println(i);}}}if (flag == 0) {System.out.println("no find");}}
}
发现问题:这样的蛮力方法对于文本中的每个字母都会进行匹配,而这无疑增加了许多冗余的比较

优化思路:KMP算法

四、蛮力法在求解“最近对”问题中的应用

最近对问题是在计算几何问题中最简单的,是指在一个包含n个点的集合中,找到距离最近的两个点,我们这里只研究二维空间中的版本,高维计算基本类似,区别只在于计算两点之间距离的公式略有不同,下面是标准的欧几里得距离公式:


class Point {int x;int y;public Point(int x, int y) {this.x = x;this.y = y;}
}
public class Main {public static void main(String[] args) {Point[] points = new Point[5];points[0] = new Point(1,3);points[1] = new Point(2,1);points[2] = new Point(3,5);points[3] = new Point(4,4);points[4] = new Point(5,2);double d = 99999999;for (int i = 0; i < points.length-1; i++) {for (int j = i+1; j < points.length; j++) {d = Math.min(d, Math.sqrt(Math.pow(points[i].x-points[j].x, 2)+Math.pow(points[i].y-points[j].y, 2)));}}System.out.println(d);}
}

由图可知,最近的两个点就是(3,5)和(4,4)

发现问题:开方计算实际上结果大多是无理数,计算机计算整数的平方根并不是一件轻松的事情,所以应该尽量在高效的算法中避免开方计算。

优化思路:全都比较未开方之前的数即可


五、蛮力法在求解凸包问题中的应用

凸包问题向来是计算几何中最重要的问题之一,许多各式各样的应用大多要么本身就是图凸包问题要么其中一部分需要按照凸包问题解决。

凸集合定义:对于平面上一个点集合,如果集合中的任意两点p和q为端点的线段都属于该集合,那么称这个集合为凸集合。

凸包定义:一个点集合S的凸包是包含S的最小凸集合。我们可以假设有一块板子,板子上面有许多钉子,用一根橡皮筋将所有的钉子都围住,凸包就是以橡皮筋圈为边界的区域。


在坐标平面上穿过两个点(x1, x2),(x2, y2)的直线方程为  ax+by = c (其中a = y2- y1, b = x1 - x2, c = x1y2 - y1x2)

上述方程基于两点式直线方程

由两个点连起来的直线会将平面分成两部分,其中半个平面的点都满足ax+by>c ,另一半平面中的点都满足ax+by<c ,对于线上的点来说满足ax+by=c。因此,算法的思路就是对于每个点带入ax+by-c,判断表达式结果的符号是否相同即可。

import java.util.*;class Point {int x;int y;public Point(int x, int y) {this.x = x;this.y = y;}@Overridepublic String toString() {return "Point{" +"x=" + x +", y=" + y +'}';}
}
public class Main {public static void main(String[] args) {Point[] points = new Point[6];List arr = new ArrayList();points[0] = new Point(1,3);points[1] = new Point(2,1);points[2] = new Point(3,5);points[3] = new Point(4,4);points[4] = new Point(5,2);points[5] = new Point(3,2);arr = outerTrees(points);Iterator it = arr.iterator();while (it.hasNext()) {System.out.println(it.next().toString() + " ");}}private static List<Point> outerTrees(Point[] points) {Set<Point> ans = new HashSet<>();/*** 只有一个点* */if (points.length == 1){ans.add(points[0]);return new ArrayList<>(ans);}for (int i = 0; i < points.length-1; i++){for (int j = i + 1; j < points.length; j++){int oneSide = 0;for (int k = 0; k < points.length; k++){if (k == i || k == j) {continue;}if (calcuTriangle(points[i], points[j], points[k]) > 0){oneSide++;}}if (oneSide == points.length-2 || oneSide == 0){ans.add(points[i]);ans.add(points[j]);}int otherSide = 0;for (int k = 0; k < points.length; k++){if (k == i || k == j) continue;if (calcuTriangle(points[i], points[j], points[k]) < 0){otherSide++;}}if (otherSide == points.length-2 || otherSide == 0){ans.add(points[i]);ans.add(points[j]);}}}return new ArrayList<>(ans);}private static int calcuTriangle(Point a1, Point a2, Point a3) {return a1.x * a2.y + a3.x * a1.y + a2.x * a3.y - a3.x * a2.y - a2.x * a1.y - a1.x * a3.y;}
}

六、蛮力法在求解最优解问题中的应用

1、TSP(旅行商问题)要求我们找出一条n个给定城市之间的最短路径,使我们再回到出发的城市之前,对欧每个城市都只访问一次。我们可以用赋权图来描述这个问题,那么算法的目的就是求解一个图的最短哈密顿回路问题。

哈密顿回路同样可以定义为


其中第一个顶点和最后一个顶点相同,其他n-1个顶点互不相同。那么我们就可以通过生成n-1个中间城市的组合来的到所哟逇旅行线路,来出最短的线路。

import java.util.Scanner;public class Main {static int[][] a = new int[5][5];static int[] bestWay = new int[6];static int min = 99999999;static int sum = 0;static Scanner in = new Scanner(System.in);public static void main(String[] args) {/*** 假设a为1号点,b为2号点,c为3号点,d为4号点* 1 2 2* 1 3 5* 1 4 7* 2 3 8* 2 4 3* 3 4 1* */for (int i = 1; i < 7; i++) {int x = in.nextInt();int y = in.nextInt();int z = in.nextInt();a[x][y] = z;a[y][x] = z;}for (int i = 2; i < a.length; i++) {for (int j = 2; j < a.length; j++) {if (j != i) {for (int k = 2; k < a.length; k++) {if (k != i && k != j) {sum = a[1][i] + a[i][j]  + a[j][k] + a[k][1];if (min > sum) {min = sum;bestWay[1] = 1;bestWay[2] = i;bestWay[3] = j;bestWay[4] = k;bestWay[5] = 1;}}}}}}for (int i = 1; i < bestWay.length-1; i++) {System.out.print(bestWay[i] + "-->");}System.out.println(bestWay[bestWay.length-1]);System.out.println(min);}
}


发现问题:我们可以发现这有3对不同的线路,而对于每队线路中,不同的只是线路的方向。

优化思路:固定住每条线路的方向,将顶点排列数目减半。

实际上用蛮力方法来解决这种问题是极为不明智的,这里只是给出一个思路,当顶点数目过多时还是要采用诸如动态规划,贪心等方法来优化的。

2、背包问题给定n个重量为w1,w2,w3...wn, 价值为v1,v2,v3...vn的物品和一个称重为C的背包,求这些物品中一个最有价值的子集。

import java.util.Scanner;public class Main {static int n, c;static int max = 0;static int[] w, v;static Scanner in = new Scanner(System.in);public static void main(String[] args) {n = in.nextInt();c = in.nextInt();w = new int[n+1];v = new int[n+1];for (int i = 1; i <= n; i++) {w[i] = in.nextInt();v[i] = in.nextInt();}/*** 对于n个物品,会存在2^n个中组合方式* 采用二进制的1,0来表示物品是否被选择,比采用数组要方便,数组每次都要遍历一遍* */for (int i = 0; i <= Math.pow(2, n); i++) {int k = i;int tempw = 0;int tempv = 0;for (int j = 1; j <= n; j++) {/*** 二进制位对应w[],v[]* 每次检查末位数字是否为1,之后数去除末位数字* */if (k % 2 == 1) {tempw += w[j];tempv += v[j];}k /= 2;}if (tempw <= c) {if (tempv > max) {max = tempv;}}}System.out.println(max);}
}
发现问题:显然2^n次的迭代始终效率都是低下的

优化思路:背包问题最好的解决方法自然是用动态规划来解决,当然也可以用回溯或者分支界限法。

3、分配问题可以理解为有n个任务需要分配给n个人执行,一个任务对应一个人。对于每一对i,j=1,2,3,...,n来说,将第j个任务分配给第i个人的成本是c[i,j],求出总成本最小的方案。我们当然不能从每一行中选出最小的元素,因为这写最小的元素可能在同一列。这个问题和旅行商问题有相似之处,基本思路也是将数据放到一个成本矩阵C中,枚举出每种情况,找出成本最小值


代码基本和TSP一样,略。

发现问题:同样是大数据量处理起来的效率问题

优化思路:匈牙利算法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/569797.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

光耦在短距离通信中的应用

在高低压隔离系统设计中&#xff0c;难免会使用光耦来通信。在选择光耦器件时&#xff0c;需要考虑光耦允许的最大通信速率&#xff0c;否则在高速通信时会失败. 对于高速的光耦应用时&#xff0c;需要注意电流传输比率和开关速度。 参考文档《Basic Characteristics and Appli…

从NetCore报错到MySql安全

从NetCore报错到MySql安全 原文:从NetCore报错到MySql安全之前项目在测试服务器上的一些接口时不时会报出下面的错误&#xff1a;&#xff08;采用Abp框架&#xff09; "SocketException: 你的主机中的软件中止了一个已建立的连接。 STACK TRACE: at MySqlConnector.Pr…

减治法在查找算法中的应用(JAVA)--快速查找

减治法在查找算法中的应用 快速查找&#xff1a;选择问题是求一个n个数列表的第k个最小元素的问题&#xff0c;这个数k被称为顺序统计量。对于k1或kn来说&#xff0c;这并没有什么意义&#xff0c;我们通常会要找出这样的元素&#xff1a;该元素比列表中一半元素大&#xff0…

JavaScript中使用Json

转载于:https://www.cnblogs.com/lyonwu/p/10368989.html

Navicat Premium试用期破解方法(转)

转载网址https://blog.csdn.net/Jason_Julie/article/details/82864187 1、按步骤安装Navicat Premium&#xff0c;如果没有可以去官网下载&#xff1a;http://www.navicat.com.cn/download/navicat-premium 2、安装好后下载激活文件&#xff1a;https://pan.baidu.com/s/1kVgT…

减治法在生成子集问题中的应用(JAVA)--递归、二进制反射格雷码

减治法在生成组合对象问题中的应用 生成子集问题&#xff1a;经典的背包问题就是求解一个最优子集的问题&#xff0c;这里我们来讨论一个更简单的问题。对于任意一个集合来说&#xff0c;它都存在2^n个子集&#xff08;一个集合所有的子集集合称为幂集&#xff09;。 1&…

减治法解决俄式乘法问题(JAVA)

以上是在《算法设计与分析基础》一书中给出的定义。 这种算法只包括折半、加倍、相加这几个操作&#xff0c;在计算时&#xff0c;不需要用九九乘法表 。 同时&#xff0c;这个方法每次都会将计算的规模减少&#xff0c;运用了减治的思想 public class Main {public static…

减治法解决尼姆(Nim)游戏/拈游戏问题(JAVA)

尼姆游戏是一种两个人玩的回合制数学策略游戏。游戏者轮流从一堆棋子&#xff08;一共有好几堆&#xff0c;一次只能从其中一堆拿。&#xff09;&#xff08;或者任何道具&#xff09;中取走一个或者多个&#xff0c;最后不能再取的就是输家。当指定相应数量时&#xff0c;一堆…

Xshell报错“The remote SSH server rejected X11 forwarding request.”

xshell连接centos7&#xff0c;报错&#xff1a;“The remote SSH server rejected X11 forwarding request.” 打开文件/etc/ssh/sshd_config,修改下面的参数 X11Forwarding yes 如果有&#xff0c;那就不用修改 修改xshell连接属性 把勾选去掉即可&#xff01; 参考&#xff…

蛮力法在求解“最近对”问题中的应用(JAVA)

最近对问题是在计算几何问题中最简单的&#xff0c;是指在一个包含n个点的集合中&#xff0c;找到距离最近的两个点&#xff0c;我们这里只研究二维空间中的版本&#xff0c;高维计算基本类似&#xff0c;区别只在于计算两点之间距离的公式略有不同&#xff0c;下面是标准的欧几…

蛮力法在求解凸包问题中的应用(JAVA)

凸包问题向来是计算几何中最重要的问题之一&#xff0c;许多各式各样的应用大多要么本身就是图凸包问题要么其中一部分需要按照凸包问题解决。 凸集合定义&#xff1a;对于平面上一个点集合&#xff0c;如果集合中的任意两点p和q为端点的线段都属于该集合&#xff0c;那么称这…

蛮力法在求解最优解问题中的应用(JAVA)--旅行家问题、背包问题、分配问题

蛮力法在求解最优解问题中的应用 1、TSP&#xff08;旅行商问题&#xff09;要求我们找出一条n个给定城市之间的最短路径&#xff0c;使我们再回到出发的城市之前&#xff0c;对欧每个城市都只访问一次。我们可以用赋权图来描述这个问题&#xff0c;那么算法的目的就是求解一个…

分治法在排序算法中的应用(JAVA)--归并排序

分治法最常用的就是将规模为n的实例划分成两个n规模为n/2的实例 。推广到一般的情况&#xff0c;我们可以将规模为n的实例划分为b个规模为n/b的实例。这样对于算法的运行时间存在递推式&#xff1a;T(n) aT&#xff08;n/b&#xff09;f&#xff08;n&#xff09;&#xff0c;…

分治法在排序算法中的应用(JAVA)--快速排序(Lomuto划分、Hoare划分、随机化快排)

分治法在排序算法中的应用--快速排序 时间复杂度&#xff1a;平均O(nlogn)&#xff0c;最坏O(n^2) 如果说归并排序是按照元素在数组中的位置划分的话&#xff0c;那么快速排序就是按照元素的值进行划分。划分方法由两种&#xff0c;本节将主要介绍Huare划分&#xff0c;这也是…

Excel中用REPT函数制作图表

本文从以下七个方面&#xff0c;阐述在Excel中用REPT函数制作图表&#xff1a; 一. 图形效果展示 二. REPT语法解释 三. REPT制作条形图 四. REPT制作漏斗图 五. REPT制作蝴蝶图 六. REPT制作柱状图 七. REPT制作甘特图 一. 图形效果展示 这些图表都是用REPT函数制作成的&#…

分治法在求解“最近对”问题中的应用(JAVA)

分治法在求解“最近对”问题中的应用 最近对问题在蛮力法中有过讲解&#xff0c;时间复杂度为O(n^2)&#xff0c;下面将会采用分治法讲解这类问题&#xff0c;时间复杂度会降到O(nlogn) 我们将笛卡尔平面上n>1个点构成的集合称为P。若2< n < 3时&#xff0c;我们1可…

【转】python的复制,深拷贝和浅拷贝的区别

在python中&#xff0c;对象赋值实际上是对象的引用。当创建一个对象&#xff0c;然后把它赋给另一个变量的时候&#xff0c;python并没有拷贝这个对象&#xff0c;而只是拷贝了这个对象的引用 一般有三种方法&#xff0c; alist[1,2,3,["a","b"]] &#x…

分治法在求解凸包问题中的应用(JAVA)--快包算法

分治法在求解凸包问题中的应用&#xff08;JAVA&#xff09; 之前写过一篇蛮力法在求解凸包问题中的应用&#xff08;JAVA&#xff09;还算简单易懂&#xff0c;没有基础的读者最好先去阅读以下。这里用分治法来求解凸包问题&#xff0c;由于这个算法和快速排序十分相似&#x…

动态规划在求解硬币问题中的应用(JAVA)--币制最大化、找零问题、硬币收集问题

动态规划&#xff1a;这种算法思想多用来求解最优化问题&#xff0c;因此这里存在一个最优化法则&#xff0c;法则指出最优化问题任一实例的最优解&#xff0c;都是由其子实例的最优解构成的。一般来说&#xff0c;自底向上的动态规划更容易设计&#xff0c;但是带有记忆功能的…

使用网络TCP搭建一个简单文件下载器

说明&#xff1a;该篇博客是博主一字一码编写的&#xff0c;实属不易&#xff0c;请尊重原创&#xff0c;谢谢大家&#xff01; 目录 一丶项目介绍 二丶服务器Server 三丶测试TCP server服务器 四丶客户端Client 五丶测试客户端向服务器下载文件 一丶项目介绍 1.叙述 生活中大家…