尚硅谷Java数据结构学习记录34- 二分查找非递归/分治/动态规划/贪心/暴力匹配/KMP

二分查找(while实现即可)easy

package Algorithm;

public class BinarySearchNo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int array[] = {1,3,8,10,11,67,100};
		int index = BinarySearch(array,1);

			System.out.println(index);
	

	}
	
	
	public static int BinarySearch(int[] array,int value) {
		int left = 0;
		int right =  array.length - 1;
		
	
		
		while(left <= right) {
			int mid = (left + right)/2;
			if(array[mid] == value) {
				return mid;
			}else if(array[mid] < value) {
				left = mid +1;
			}else{
				right = mid - 1;
			}
		}
		return -1;
		
	} 

}

分治 汉诺塔问题求解

package Algorithm;

public class Hanoitower {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
			hanoiTower(4,'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 {
			//先将num-1个盘从a经过c到b
			hanoiTower(num-1, a,c,b);
			//将最后一个盘从a到c
			System.out.println("第"+ num + "个盘从" + a + "->" + c);
			//num-1个盘从b经过a到c
			hanoiTower(num-1, a,b,c);

		}
	}
}

动态规划 背包问题 动态规划问题下一步骤要考虑上一次的决策

package Algorithm;

public class dynamic {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] w = {1,4,3}; //物品的重量
		int[] val = {1500,3000,2000};
		int n = val.length; //物品的个数
		int m = 4;//背包容量
		//为了计入放入商品的情况,定义二维数组
		int[][] path = new int[n+1][m+1];
		
		
		//创建二维数组 v v[i][j]表示在前i个物品中能够装入容量我ij的背包中的最大价值
		int[][] v = 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;
		
		
//		for(int i = 0; i < v.length; i++) {
//			for(int j = 1; j < v[0].length; j++)
//				System.out.println(v[i][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 {
					
					//因为是从1 开始的 公式需要调整
					//v[i][j] = Math.max(v[i-1][j],val[i-1] + v[i-1][j-w[i-1]]);
					//为了记录商品放入背包的情况,不能简单使用上式
					if(v[i-1][j] < val[i-1] + v[i-1][j-w[i-1]]) {
						v[i][j] = val[i-1] + v[i-1][j-w[i-1]];
						path[i][j] = 1;
					}else {
						v[i][j] = val[i-1];
					}
				}
		}
		
		for(int i = 0; i < v.length; i++) {
		for(int j = 1; j < v[0].length; j++) {
			System.out.printf(v[i][j] + " ");
			
		}
		System.out.println();
			
	}
		
//		for(int i = 0; i < path.length; i++) {
//			for(int j = 1; j < path[0].length; j++)
//				if(path[i][j] == 1)
//					System.out.printf("第%d个商品放入背包\n",i);
//		}
//	}
//	
	int i = path.length -1;
	int j = path[0].length -1;
	while(i >0 && j >0) {
		//逆序输出}
		if(path[i][j]==1) {
			System.out.printf("第%d个商品放入背包\n",i);

			j -= w[i-1];
		}
		i--;

	}
	}

}

贪心算法的本质是每次寻找最大最好的那一个

package Algorithm;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

public class GreedyAlgorithm {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//创建广播电台,放入到Map
		//将各个电台放入到broadcasts
		HashMap<String,HashSet<String>> broadcasts = new HashMap<String,HashSet<String>>(); 
		//将各个电台放入到broadcasts
		HashSet<String> hashSet1 = new HashSet<String>();
		hashSet1.add("北京");
		hashSet1.add("上海");
		hashSet1.add("天津");
		
		HashSet<String> hashSet2 = new HashSet<String>();
		hashSet2.add("广州");
		hashSet2.add("北京");
		hashSet2.add("深圳");
		
		HashSet<String> hashSet3 = new HashSet<String>();
		hashSet3.add("成都");
		hashSet3.add("上海");

		hashSet3.add("杭州");
		
		
		HashSet<String> hashSet4 = new HashSet<String>();
		hashSet4.add("天津");
		hashSet4.add("上海");
		
		HashSet<String> hashSet5 = new HashSet<String>();
		hashSet5.add("杭州");
		hashSet5.add("大连");
		
		//加到到Map
		broadcasts.put("K1", hashSet1);
		broadcasts.put("K2", hashSet2);
		broadcasts.put("K3", hashSet3);
		broadcasts.put("K4", hashSet4);
		broadcasts.put("K5", hashSet5);

		
		//allAreas存放所有的地区
		HashSet<String> allAreas = new HashSet<String>();
		allAreas.add("北京");
		allAreas.add("上海");
		allAreas.add("天津");
		allAreas.add("广州");
		allAreas.add("深圳");
		allAreas.add("成都");
		allAreas.add("杭州");
		allAreas.add("大连");
		
		//创建ArrayList,存放选择的电台集合
		ArrayList<String> selects = new ArrayList<String>();
		//定义一个临时的集合,在遍历的过程中,存放遍历过程中的电台覆盖的地区和当前还没有覆盖的地区的交集
		HashSet<String> tempSet = new HashSet<String>();
		//定义给maxKey,保存在一次遍历过程中,能够覆盖最大未覆盖的地区对应的电台的Key
		//如果maxKey 不为Null,则加入到selects
		String maxKey = null;
		while(allAreas.size()!= 0) {
			//遍历broadcasts,取出对应key
			maxKey = null;
			for(String key : broadcasts.keySet()) {
				//当前这个key能够覆盖的地区
				tempSet.clear();
				HashSet<String> areas = broadcasts.get(key);
				tempSet.addAll(areas);
				//求出tempSet和allAread集合的交集,交集会赋给tempSet
				tempSet.retainAll(allAreas);
				
				if(tempSet.size() > 0 && ( maxKey == null || tempSet.size() > broadcasts.get(maxKey).size() )) {
					maxKey = key;
				}
			}
			
			if(maxKey != null) {
				selects.add(maxKey);
				allAreas.removeAll(broadcasts.get(maxKey));
			}
		}
		System.out.println("得到的选择结果是" + selects);


	}

}

暴力破解

package Algorithm;

public class ViolenceMatch {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String str1 ="我爱学习 学习爱我吗";
		String str2 ="学习爱我";
		int index = violenceMatch(str1,str2);
		System.out.println("index:" + index);
	}
	
	//暴力匹配算法实现
	public static int violenceMatch(String str1,String str2) {
		char[] s1 = str1.toCharArray();
		char[] s2 = str2.toCharArray();
		
		int s1len = s1.length;
		int s2len = s2.length;
		
		int i = 0; //i索引指向s1
		int j = 0; //j索引指向s2
		
		while(i < s1len && j < s2len) {
			if(s1[i] == s2[j]) {
				//匹配成功
				i++;
				j++;
			}else {
				//没有匹配成功
				i -= j-1;
				j = 0;
			}
		}
		
		if( j == s2len)
			return i-j;
		else
			return -1;
		
	}

}

KMP算法!!!重要!!!难懂

KMP用了两次临时数组。第一次是在要比较的数组中,用来找到数组是否有重复的元素,如题中ABCDABD,AB显然是重复的,所以在匹配不下的情况下,我们可以直接从跳四个进行重新查找,这样就加快了查找效率。所以在要比较的数组中,它的索引是0000 1 2 0 ,这表明只有A B 是可以的。再详细的讲,再kmpNext函数中,一个索引从1开始,一个索引从0开始,由于两个字符不相等,索引从1 开始的一直在++,去匹配索引从0开始的值,一旦匹配到值,则从0开始的索引++,一旦不匹配,将从0开始的索引--,看是否匹配,如果不匹配则再次--,直到j=0(这是一个while循环)。这样就理解了第一个临时数组。如题中的next;第二个临时数组是在实际的比较中,如果发现了不匹配,此时使用next中的索引,直接跳到该去的位置继续查询

package Algorithm;

import java.util.Arrays;

public class KMP {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String str1 = "BBC ABCDAB ABCDABCDABDE";
		String str2 = "ABCDABD";
		int[] next = kmpNext("ABCDABD");
		System.out.println("next=" + Arrays.toString(next));
		int index = kmpSearch(str1,str2,next);
		System.out.println("index=" + index);

	}
	
	//遍历
	public static int kmpSearch(String str1,String str2,int[] next) {
		//遍历
		for(int i = 0, j = 0; i < str1.length(); i++) {
			while( j > 0 && str1.charAt(i)!= str2.charAt(j)) {
				j = next[j-1];
			}
			if(str1.charAt(i)== str2.charAt(j))
				j++;
			if(j == str2.length()) {
				return i - j + 1;
				
			}
		}
		return -1;
	}
	
	
	//获取一个字符串的部分匹配表
	public static int[] kmpNext(String dest) {
		//创建一个next数组保存有部分匹配表
		int[] next = new int[dest.length()];
		next[0] = 0;//如果字符串长度为1,部分匹配表就是0
		for(int i = 1,j = 0; i < dest.length(); i++) {
			//当dest.charAt(i) == dest.charAt(j)
			while(j > 0 && dest.charAt(i)!= dest.charAt(j)) {
				j = next[j-1];
			}
			if(dest.charAt(i)== dest.charAt(j)) {
				j++;
			}
			next[i] = j;
		}
		return next;
	}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值