一、 二分查找算法(非递归)
二分查找算法(非递归)介绍
二分查找算法(非递归)代码实现
数组 {1,5,8,9,10,20}, 编程实现二分查找, 要求使用非递归的方式完成.
package xyz.changlu.binarySearchAlgorithm;
public class BinarySearch {
public static void main(String[] args) {
int[] arr = {1,5,8,9,10,20};
int valueCur = binarySearch(arr, 30);
if(valueCur != -1) {
System.out.println("找到值为1的位置,位置为:"+valueCur);
}else {
System.out.println("未找到值为1的位置");
}
}
//非递归进行查找
public static int binarySearch(int[] arr,int findValue) {
int left = 0;
int right = arr.length-1;
while(left<=right) {
int mid = (left+right)/2;
//如果找到了
if(findValue == arr[mid]) {
return mid;//返回下标
}else if(findValue<arr[mid]) {//如果查找值比中间值小
right = mid - 1;
}else {//如果查找值比中间值大
left = mid + 1;
}
}
return -1;
}
}
运行结果:
**
二、分治算法
1、分治算法介绍
2、分治算法的基本步骤
分治法在每一层递归上都有三个步骤:
1) 分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题
2) 解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题
3) 合并:将各个子问题的解合并为原问题的解。
3、分治(Divide-and-Conquer(P))算法设计模式如下
4、汉诺塔(分治)
汉诺塔的传说
汉诺塔游戏的演示和思路分析
代码实现
说明:采用了分治的算法,层层递归下去
package xyz.changlu.dac;
public class Hanoitower {
public static void main(String[] args) {
hanoitower(3, 'a', 'b', 'c');
}
public static void hanoitower(int n, char a, char b, char c) {
if (n == 1) {
System.out.println(a + "->" + c);
} else {
hanoitower(n - 1, a, c, b);
System.out.println(a + "->" + c);
hanoitower(n - 1, b, a, c);
}
}
}
三、动态规划算法
1、应用场景-背包问题
2、动态规划算法介绍
3、动态规划算法最佳实践-01背包问题
题意分析
注意这里的两个要求,物品不能重复以及背包总价值最大且重量不超出
思路分析和图解(包含示例)
示例:
代码实现
(1)打印填充的对应表(未完善)
package dynamic;
//背包问题
public class KnapsackProblem {
public static void main(String[] args) {
//设置一维数组 分别是记录商品的价格(v表示value)以及商品的重量(w表示weight)
//注意这里第一个位置留空为0 有用数据为下标0之后的
int[] v = {0,1500,3000,2000};
int[] w = {0,1,4,3};
int n = 4;//表示背包中能够存放4磅物品
int m = v.length-1;//用于表示有几件商品
//定义一个二维数组 用来存放商品的总金额
//行下标1 2 3对应着的v数组的下标1 2 3 行数为商品数量
//列下标1 2 3 4代表着1磅 2磅 3磅 4磅等情况 列数为总磅数数量
int[][] vs = new int[m+1][n+1];//行列都需要空出来一行一列为0
//行列从第一行第一列开始计算
for(int i = 1;i<vs.length;i++) {
for(int j = 1;j<vs[i].length;j++) {
//如果要添加的商品大于当前列对应磅数 来存取上一件物品(i-1)对应的金额
if(w[i]>j) {
vs[i][j] = vs[i-1][j];
}else if(j>=w[i]) {
//vs[i-1][j]与v[i]+vs[i-1][j-w[i]]作比较
//vs[i-1][j]表示对应磅数上一件物品的存取金额
//v[i]+vs[i-1][j-w[i]] 表示当前物品金额+上一件物品的(当前列磅数-当前物品磅数)位置的存放金额
vs[i][j] = Math.max(vs[i-1][j], v[i]+vs[i-1][j-w[i]]);
}
}
}
//用于打印二维数组数据
for (int i = 0; i < vs.length; i++) {
for (int j = 0; j < vs[i].length; j++) {
System.out.print(vs[i][j]+" ");
}
System.out.println();
}
}
}
运行结果:
(2)打印出对应背包的商品项(完善)
修改部分:
对应path表的值:
package dynamic;
//背包问题
public class KnapsackProblem {
public static void main(String[] args) {
//设置一维数组 分别是记录商品的价格(v表示value)以及商品的重量(w表示weight)
//注意这里第一个位置留空为0 有用数据为下标0之后的
int[] v = {0,1500,3000,2000};
int[] w = {0,1,4,3};
int n = 4;//表示背包中能够存放4磅物品
int m = v.length-1;//用于表示有几件商品
//定义一个二维数组 用来存放商品的总金额
//行下标1 2 3对应着的v数组的下标1 2 3 行数为商品数量
//列下标1 2 3 4代表着1磅 2磅 3磅 4磅等情况 列数为总磅数数量
int[][] vs = new int[m+1][n+1];//行列都需要空出来一行一列为0
//为了记录商品的情况
int[][] path = new int[m+1][n+1];
//行列从第一行第一列开始计算
for(int i = 1;i<vs.length;i++) {
for(int j = 1;j<vs[i].length;j++) {
//如果要添加的商品大于当前列对应磅数 来存取上一件物品(i-1)对应的金额
if(w[i]>j) {
vs[i][j] = vs[i-1][j];
}else if(j>=w[i]) {
//vs[i-1][j]与v[i]+vs[i-1][j-w[i]]作比较
//vs[i-1][j]表示对应磅数上一件物品的存取金额
//v[i]+vs[i-1][j-w[i]] 表示当前物品金额+上一件物品的(当前列磅数-当前物品磅数)位置的存放金额
//vs[i][j] = Math.max(vs[i-1][j], v[i]+vs[i-1][j-w[i]]);
//与上面相同
if(vs[i-1][j]>v[i]+vs[i-1][j-w[i]]) {
vs[i][j] = vs[i-1][j];
}else {
vs[i][j] = v[i]+vs[i-1][j-w[i]];
//这里多出来步骤 将信息存入到path数组中
path[i][j] = 1;
}
}
}
}
//用于打印二维数组数据
for (int i = 0; i < vs.length; i++) {
for (int j = 0; j < vs[i].length; j++) {
System.out.print(vs[i][j]+" ");
}
System.out.println();
}
System.out.println("============================");
//获取到行数列数
int i = path.length-1;
int j = path[0].length-1;
//从path的最后开始找
while(i>0&&j>0) {
if(path[i][j] == 1) {
System.out.println("移入"+i+"到背包");
j -= w[i];
}
i--;
}
}
}
运行结果:
四、kmp算法(解决两个字符串匹配)
应用场景-字符串匹配问题
第一种解决方法(暴力匹配)
解决思路
代码实现
package kmp;
public class ViolenceMatch {
public static void main(String[] args) {
String str1 = "硅硅谷 尚硅谷你尚硅 尚硅谷你尚硅谷你尚硅你好";
String str2 = "尚硅谷你尚硅你";
int index = violenceMatch(str1, str2);
System.out.println("对应位置为:"+index);
}
//进行暴力匹配字符串
public static int violenceMatch(String str1,String str2) {
//将字符串转为char型数组
char[] c1 = str1.toCharArray();
char[] c2 = str2.toCharArray();
//获取两个字符数组的长度
int len1 = c1.length;
int len2 = c2.length;
//设置两个移标来指向两个字符数组 i指向c1 j指向c2
int i = 0;
int j = 0;
//通过两个移标越界判断结束
while(i<len1 && j<len2) {
//判断两个移标指向位置是否相同
if(c1[i] == c2[j]) {
i++;
j++;
}else {
//不相同的情况
i = i-j+1;//这里从原本位置向后移一位
j = 0;
}
}
//如果while出来j对应下标为c2的长度那么就说明全部字段都匹配到了
if(j == len2) {
//从而获取c1中初始匹配到的位置
return i-j;
}else {
//没有找到返回-1
return -1;
}
}
}
运行结果:
第二种解决方法(kmp算法) 未懂
整理者:长路 时间:2020/9/4-2020/9/6