一、 二分查找算法(非递归)
二分查找算法(非递归)介绍

二分查找算法(非递归)代码实现
数组 {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指向c2int 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 {//没有找到返回-1return -1;}}}
运行结果:
第二种解决方法(kmp算法) 未懂
整理者:长路 时间:2020/9/4-2020/9/6
