二分查找(非递归)
package binarysearchnorecursion;
public class BinarySearchNoRecur {
public static void main(String[] args) {
int[] arr = {
1,3,8,10,11,67,100};
System.out.println(binarySearch(arr,-8));
}
public static int binarySearch(int[] arr,int target){
int left = 0;
int right = arr.length-1;
while(left <= right){
int mid = (left + right)/2;
if(arr[mid] == target){
return mid;
}else if(arr[mid] > target){
right = mid -1;
}else{
left = mid +1;
}
}
return -1;
}
}
分治算法
1.思想介绍:
a.分解,将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题
b.解决,如果若干个小问题比较好解决,就直接解决,否则递归解决
c.合并,将若干个小问题的解合起来就是原问题的解
2.能解决的问题
二分搜索,归并排序,快速排序,汉诺塔
3.汉诺塔问题分析
a.如果只有一个盘,就直接将盘从A移动到C
b.如果盘数大于等于2,将所有盘分为两部分,最后一个盘自己一部分,剩下的盘一部分
c.先将剩下的盘移动到B,再将最后一个盘移动到C,最后将剩下的盘从B移动到C
4.代码实现
package dac;
public class Hanoitower {
public static void main(String[] args) {
hanoitower(3,'A','B','C');
}
public static void hanoitower(int num,char a,char b,char c){
if(num == 1){
System.out.println("将第1个盘从"+a+"移动到"+c);
}else{
hanoitower(num-1,a,c,b);
System.out.println("将第"+num+"个盘从"+a+"移动到"+c);
hanoitower(num-1,b,a,c);
}
}
}
动态规划算法
1.算法思想:与分治算法类似,也是将大问题转换成小问题,再解决小问题,区别在于动态规划算法,下一个子阶段的求解是建立在上一个子阶段的基础上,而分治算法,每个子阶段都是独立的
2.背包问题问题描述:
3.问题分析
a.分析动态规划算法可以使用画图的方式
b.从上面的表格我们可以总结出规律:v[i][j]表示前i个物品能装入容量为j的容器的最大价值,val[i]表示第i个物品的价值,w[i]表示第i个物品的重量
v[i][0] = j[0][j] = 0表示第一行第一列全部为空
如果w[i]>j,代表当前物品的容量大于背包能承受的容量,所以直接延续上一个v[i][j] = v[i-1][j]
如果w[i]<=j,v[i][j] = max{v[i-1][j],val[i]+v[i-1][j-w[i]]},此时背包容量可以装下当前物品,所以就先装入当前物品,再去找剩下的容量可以装下的物品(最大价值)与上一个做对比,找到二者中最大的
4.代码实现
package dynamic;
public class KnapsackProblem {
public static void main(String[] args) {
int[] w = {
1,4,3};//物品重量
int[] vals = {
1500,3000,2000};//物品价值
int m = 4 ;//背包容量
int n = w.length;//物品个数
//表示前i个物品能装入容量为j的容器的最大价值
int[][] v = new int[n+1][m+1];
//标记可能出现的最大值
int[][] path = new int[n+1][m+1];
//将第一行第一列设置为空
for(int i=0;i<v.length;i++){
v[i][0] = 0;
}
for(int i=0;i<v[0].length;i++){
v[0][i] = 0;
}
//比较w[i-1]与j的大小关系,分别填入数据
for(int i=1;i<v.length;i++){
for(int j=1;j<v[0].length;j++){
if(w[i-1]>j){
v[i][j] = v[i-1][j];
}else{
if(v[i-1][j]<vals[i-1]+v[i-1][j-w[i-1]]){
v[i][j] = vals[i-1]+v[i-1][j-w[i-1]];
path[i][j] = 1;
}else{
v[i][j] = v[i-1][j];
}
}
}
}
for(int i=0;i<v.length;i++){
for(int j=0;j<v[i].length;j++){
System.out.print(v[i][j]+" ");
}
System.out.println();
}
for(int i=0;i<v.length;i++){
for(int j=0;j<v[i].length;j++){
System.out.print(path[i][j]+" ");
}
System.out.println();
}
//找到最大匹配方式,从后向前找
int i = path.length-1;
int j = path[0].length-1;
while (i>0 && j>0){
if(path[i][j]==1){
System.out.println(i);
j -= w[i-1];
}
i--;
}
}
}
暴力匹配和KMP算法
1.暴力匹配(字符串)思路分析:
假设有字符串S1,S2,我们用S2(指针j)去S1(指针i)里面匹配,从0开始一个字符一个字符对比,如果相同就同时后移,如果发现不同S2指针直接移动到0,S1移动到i-j+1,再次匹配,此时效率很低
2.代码实现
package kmp;
public class ViolenceMatch {
public static void main(String[] args) {
String str1 = "AABCEDERQWWE";
String str2 = "RQq";
System.out.println(violenceMatch(str1,str2));
}
public static int violenceMatch(String str1,String str2){
char[] chars1 = str1.toCharArray();
char[] chars2 = str2.toCharArray();
int length1 = str1.length();
int length2 = str2.length();
int i=0;
int j=0;
while(i<length1 && j<length2){
if(chars1[i] == chars2[j]){
i++;
j++;
}else{
i = i-j+1;
j=0;
}
}
if(j == length2){
return i-j;
}
return -1;
}
}
3.KMP算法思路分析
KMP和暴力匹配最大的不同在于,发现不同时,KMP并非是移动1位,而是通过算法移动n位,这样提高效率,在使用KMP时首先需要创造出部分匹配表,在使用部分匹配表完成移位,提高效率
4.代码实现
package kmp;
import java.util.Arrays;
public class KMPAlgorithm {
public static void main(String[] args) {
String str1 = "BBC ABCDAB ABCDABCDABDE";
String str2 = "ABCDABD";
int[] next = kmpNext(str2);
System.out.println(Arrays.toString(kmpNext(str2)));
System.out.println(kmp(str1,str2,next));
}
public static int kmp(String str1,String str2,int[] next){
for(int i=0,j=0;i<str1.length();i++){
while(j>0 && str1