使用费曼算法解决算法入门问题(2)-日更ing
二分查找
传统的查找方式则是把待查找的数据放到数据列表里一个个比对,如果有n个数据,最坏情况下需要的时间为O(n);现在,设想一下,假如你有一个有序数组,在这个数组里查找指定数据,有没有什么比简单查找更快的方法呢?
比如,现在你有一组数据{1,2,3,4,5,6,7},要再其中查找6这个数字.使用简单查找一个个比对需要查找6次;而你拿出中间的那个数据4,拿6和它比较,6>4,那么1-4都可以排除在外,现在只剩下{5,6,7}三个数据,再把中间的数据6拿出来,6==6,只用了俩次就找到了指定的数据.
二分排序就是在有序数据里,每次拿出中间的数据进行比较,每次可以排除一半的数据,
package com.first.boke; public class BinaryBoke { public int findNum(int num,int[] nums){ int low = 0; int high = nums.length - 1; int mid; while(low<=high){ mid = (low+high)/2; if (num == nums[mid]){ return nums[mid]; }else if (num < nums[mid]){ high = mid-1; }else { low = mid +1; } } return -10000000; } }
动态规划
背包问题
假如你是一个小偷,你的背包大小为4kg,现在可偷物品如下: 音响:3000$ 4kg 笔记本电脑:2000$ 3kg 吉他:1500$ 1kg iphone:2000$ 1kg 如何偷可以使总物品价值最大
这个问题你可以使用简单算法,一个个枚举得出结果,不过要是可偷物品变多了呢?其时间复杂度需要O(2^n).
要是想简化问题,我们可以使用分而治之的办法,将大问题划分为子问题,再着手解决子问题,比如在可偷物品只有音响,背包容量为一的时候,怎么偷物品总价值最大,只有音响背包容量为二该怎么做…可偷物品加上笔记本电脑,容量为一时怎么做…所有物品都可偷,背包容量为4的时候该怎么做?
一步步解决子问题继而解决最终问题;列表如下:
背包容量 : 1 2 3 4
可偷物品-------------------------------------
音响
笔记本电脑
吉他
iphone
很像一个二维数组吧!!!
把子问题的答案填入:
背包容量 : 1 2 3 4
可偷物品------------------------------------------------------
音响 0 0 0 3000
笔记本电脑 0 0 2000 3000
吉他 1500 1500 2000 3500
iphone 2000 3500 3500 4000
这样做确实一目了然,但是如何让计算机来做这件事情呢?
伪代码如下
如果是第一行:
那么只需要在特定质量的位置及之后的位置填上当前物品的价值,剩下的全部为0
如果不是第一行:
上一列的这行 与 (当前物品价格+上一列的(下标-当前物品质量)列) 中较大的那个
代码实现如下:
package com.ninth.dynamic_programming; /** * 假如你是一个小偷,你的背包大小为4kg,现在可偷物品如下 * 音响:3000$ 4kg 笔记本电脑:2000$ 3kg 吉他:1500$ 1kg iphone:2000$ 1kg */ public class PackageProblem { public static void main(String[] args) { Goods[] goods = new Goods[4]; goods[0] = new Goods("音响",3000,4); goods[1] = new Goods("笔记本电脑",2000,3); goods[2] = new Goods("吉他",1500,1); goods[3] = new Goods("iphone",2000,1); int[][] nums = new int[4][4]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (i == 0){ nums[i][j] = ((j+1)>=goods[i].getQuality())?goods[i].getMoney():0; }else{ if (j-goods[i].getQuality()>=0){ nums[i][j] = nums[i-1][j]>(goods[i].getMoney()+nums[i-1][j-goods[i].getQuality()])? nums[i-1][j]:(goods[i].getMoney()+nums[i-1][j-goods[i].getQuality()]); }else { if (j-goods[i].getQuality() == -1){ nums[i][j] = nums[i-1][j]>goods[i].getMoney()? nums[i-1][j]:goods[i].getMoney(); }else { nums[i][j] = nums[i-1][j]; } } } } } for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { System.out.print(nums[i][j]+"\t"); } System.out.println(); } System.out.println("能偷走的货物最大价值为"+nums[3][3]+"$"); } } class Goods{ private String name; private int money; private int quality; public Goods(String name, int money, int quality) { this.name = name; this.money = money; this.quality = quality; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } public int getQuality() { return quality; } public void setQuality(int quality) { this.quality = quality; } }