目录
蛮力法的定义:
蛮力法的适用场景:
1、搜索所有的解空间:
2、搜索所有的路径:
3、直接计算:
4、模拟和仿真:
蛮力法的具体应用案例:
1、简单选择排序和冒泡排序:
2、求解最大连续子序列和问题:
3、求解幂集问题:
4、求解全排列问题:
5、求解组合问题:
6、求解迷宫问题:
蛮力法的定义:
对问题中的所有可能状态都进行测试,直到找到解或将全部可能状态都测试为止。
蛮力法的适用场景:
1、搜索所有的解空间:
问题的解存在于规模不大的解空间中。解决这类问题一般是找出某些满足特定条件或要求的解。使用蛮力法就是把所有的解都列出来,从中选出符合要求的解。
2、搜索所有的路径:
这类问题中不同的路径对应不同的解,需要找出特定解。使用蛮力法搜索所有可能的路径并计算路径对应的解,找出特定解。
3、直接计算:
基于问题的描述直接进行计算。
4、模拟和仿真:
根据问题要求直接模拟或仿真。
蛮力法的具体应用案例:
1、简单选择排序和冒泡排序:
简单选择排序代码展示:
package test;
public class Test {
public static void main(String[] args) {
int[] a= {7,3,5,9,4,2};
sort(a);
for(int i=0;i<a.length;i++)
System.out.println(a[i]);
}
private static void sort(int[] nums) {
for(int i=0;i<nums.length;i++) {
int k=i;
for(int j=i+1;j<nums.length;j++)
if(nums[k]>nums[j])
k=j;
if(k!=i) {
int temp=nums[i];
nums[i]=nums[k];
nums[k]=temp;
}
}
}
}
冒泡排序代码展示:
package test;
public class Test {
public static void main(String[] args) {
int[] a= {7,3,5,9,4,2};
sort(a);
for(int i=0;i<a.length;i++)
System.out.println(a[i]);
}
private static void sort(int[] nums) {
for(int i=0;i<nums.length;i++) {
boolean exchange=false;
for(int j=nums.length-1;j>i;j--) {
if(nums[j]<nums[j-1]) {
int temp=nums[j];
nums[j]=nums[j-1];
nums[j-1]=temp;
exchange=true;
}
}
if(!exchange)
break;
}
}
}
2、求解最大连续子序列和问题:
思路:用一个变量sum表示当前子数组的最大和,用另一个变量max表示最终子数组最大和,然后从头到尾扫描整个数组,每扫描一个元素之前先判断sum是否小于0,若小于则将sum置为0;然后将sum加上扫描的元素,最后max取sum和max中的最大值。扫描一遍数组,答案就出来了,此方法的时间复杂度为O(n),而分治法解决此问题的时间复杂度为
,故此方法效率更高。
完整代码展示:
package leetcode_7;
public class T_O_42 {
public static void main(String[] args) {
int[] a= {-2,1,-3,4,-1,2,1,-5,4};
System.out.println(maxSubArray(a));
}
public static int maxSubArray(int[] nums) {
int max=nums[0],sum=nums[0];
for(int i=1;i<nums.length;i++) {
if(sum<0)
sum=0;
sum+=nums[i];
max=Math.max(max, sum);
}
return max;
}
}
3、求解幂集问题:
思路:采用增量穷举法求解,此处借助了ArrayList。可以通过遍历或递归实现。
完整代码展示(遍历实现):
package leetcode_7;
import java.util.ArrayList;
import java.util.List;
public class T_mst0804 {
public static void main(String[] args) {
int[] a= {1,2,3};
System.out.println(subsets(a));
}
public static List<List<Integer>> subsets(int[] nums){
List<List<Integer>> ans=new ArrayList();
List<Integer> p=new ArrayList();
ans.add(p);
for(int i=0;i<nums.length;i++) {
int n=ans.size();
for(int j=0;j<n;j++) {
List<Integer> t=new ArrayList(ans.get(j));
t.add(nums[i]);
ans.add(t);
}
}
return ans;
}
}
完整代码展示(递归实现):
package leetcode_7;
import java.util.ArrayList;
import java.util.List;
public class T_mst0804 {
public static void main(String[] args) {
int[] a= {1,2,3};
System.out.println(subsets(a));
}
public static List<List<Integer>> subsets(int[] nums){
List<List<Integer>> ans=new ArrayList();
ans.add(new ArrayList());
f(nums,0,ans);
return ans;
}
private static void f(int[] nums,int n,List<List<Integer>> ans) {
if(n>=nums.length)
return ;
int count=ans.size();
for(int i=0;i<count;i++) {
List<Integer> t=new ArrayList(ans.get(i));
t.add(nums[n]);
ans.add(t);
}
f(nums,n+1,ans);
}
}
4、求解全排列问题:
思路:也是采用增量穷举法求解,此处借助了LinkedList。同样也可以通过遍历或递归实现。
完整代码展示(遍历实现):
package leetcode_7;
import java.util.LinkedList;
import java.util.List;
public class T_46 {
public static void main(String[] args) {
int[] a= {1,2,3};
System.out.println(permute(a));
}
public static List<List<Integer>> permute(int[] nums){
List<List<Integer>> ans=new LinkedList();
List<Integer> p=new LinkedList();
p.add(nums[0]);
ans.add(p);
for(int i=1;i<nums.length;i++) {
int n=ans.size();
for(int j=0;j<n;j++) {
List<Integer> t=new LinkedList(ans.get(0));
ans.remove(0);
int m=t.size();
for(int k=0;k<=m;k++) {
List<Integer> q=new LinkedList(t);
q.add(k, nums[i]);
ans.add(q);
}
}
}
return ans;
}
}
(ArrayList与LinkedList的区别:ArrayList使用顺序存储结构存储对象元素,故其查找、遍历元素快,插入、删除元素慢;LinkedList使用链表结构存储元素,故其插入、删除元素快,查找、遍历元素慢。)
5、求解组合问题:
思路:采用递归解决,大问题:从n个数中找k个数,小问题:从m个数中找k-1个数。(k-1<=m<n)当k=0时说明这是其中的一个组合,将其加入所求集合中。
完整代码展示:
package leetcode_7;
import java.util.LinkedList;
import java.util.List;
public class T_77 {
public static void main(String[] args) {
System.out.println(combine(4,2));
}
public static List<List<Integer>> combine(int n, int k){
List<List<Integer>> ans=new LinkedList();
List<Integer> p=new LinkedList();
f(n,k,ans,p);
return ans;
}
private static void f(int n,int k,List<List<Integer>> ans,List<Integer> t) {
if(k==0) {
ans.add(t);
return ;
}
for(int i=k;i<=n;i++) {
List<Integer> q=new LinkedList(t);
q.add(i);
f(i-1,k-1,ans,q);
}
}
}
6、求解迷宫问题:
问题:有一个8x8的迷宫如下图所示,其中O表示通路方块,X表示障碍方块。假设入口位置为(0,0),出口为右下角方块位置(7,7)。设计一个程序求指定入口到出口的一条迷宫路径。
迷宫
O | X | X | X | X | X | X | X |
O | O | O | O | O | X | X | X |
X | O | X | X | O | O | O | X |
X | O | X | X | O | X | X | O |
X | O | X | X | X | X | X | X |
X | O | X | X | O | O | O | X |
X | O | O | O | O | X | O | O |
X | X | X | X | X | X | X | O |
思路:采用枚举的思想解决此题,可通过DFS或BFS去实现。
完整代码展示(DFS):
package test;
public class Test3 {
public static void main(String[] args) {
char[][] maze={{'O','X','X','X','X','X','X','X'},
{'O','O','O','O','O','X','X','X'},
{'X','O','X','X','O','O','O','X'},
{'X','O','X','X','O','X','X','O'},
{'X','O','X','X','X','X','X','X'},
{'X','O','X','X','O','O','O','X'},
{'X','O','O','O','O','X','O','O'},
{'X','X','X','X','X','X','X','O'}};
dfs(0,0,maze);//设置起点位置为左上角
}
private static void dfs(int x,int y,char[][] maze) {
int row=maze.length,col=maze[0].length;
if(x==col-1&&y==row-1) {//设置终点的位置为右下角
for(int i=0;i<row;i++) {
for(int j=0;j<col;j++)
System.out.print(maze[i][j]+" ");
System.out.println();
}
return ;
}
int[] H= {0,1,0,-1};
int[] V= {-1,0,1,0};
for(int k=0;k<4;k++) {
if(0<=x&&x<col&&0<=y&&y<row&&maze[x][y]=='O') {
maze[x][y]='T';
dfs(x+H[k],y+V[k],maze);
maze[x][y]='O';//如果退回来就恢复迷宫此处初始值
}
}
}
}