博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
贪心算法思路总结及其java实现
阅读量:4113 次
发布时间:2019-05-25

本文共 3448 字,大约阅读时间需要 11 分钟。

1. 贪心算法条件与思路的解题步骤

1.一次性:某个状态以后的过程不会影响以前的状态,只与当前状态有关。

2.局部最优集合能得到全局最优。
(如果某次选择会对之后选择产生影响,局部最优不能获得全局最优可以直接KO贪心思路)
第一步,判断是否属于贪心算法的情况:对一组数据加了一定的限制,希望从中选出几个数据,在满足限制值的情况下,达到最大期望值。
第二步,用简单例子检测贪心算法是否最优。

2.贪心算法的分类

依据个人经验分成了三大类

1.分饼干,跳跃游戏,环绕加油站等每次从最小的开始分配

从问题的某一初始解出发;    while (到达目标边界)    {         if(该阶段的状态满足最优条件)加入此局部最优解;          进入下一阶段;    }    return 由所有解元素组合成问题的一个可行解;
  1. 教师排课器,任务调度等区间覆盖的问题
    选择几个不相交的区间,从左到右将[lmin, rmax]覆盖上。按照起始端从小到大对这 n 个区间排序。
    每次选择:左端点跟前面已覆盖区间不重合的、尽量小的区间,这样可以让剩下的未覆盖区间尽可能的大,就可以放置更多的区间。
  2. 背包价值和钱币找零问题
    贡献相同期望值的情况下,每次价值越大,总体的数量/重量就更少

注:求最小生成树的Prim算法和Kruskal算法都是漂亮的贪心算法。

leetcode里贪心算法的代码实现

1.简单题455分发饼干
import java.util.Arrays; public class AssignCookie{
public static int contentChildren(int[]g,int[]s){
assert g.length>0||s.length>0; Arrays.sort(g); Arrays.sort(s); //定义第i个小孩的appetite对应第j块饼干 int i=0,j=0; //当小孩没满足完或饼干没发完 while(i
中等题134. 加油站
/** *在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。 * 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。 * 如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。 */public class GasStation {
/** *一旦遇到第一个无法到达的点 i,直接更换起始点为 i+1。中间的 [1,i-1] 的点一定不是起始点 * @param gas * @param cost */ public int canCompleteCircuit(int[] gas, int[] cost) {
int sum = 0;//选定起点到现在的油缸量 int total = 0;//总的加油与耗油差值 int result = 0;//选定的起点 for(int i = 0;i
=0?result:-1; }}
贪心算法简单题392. 判断子序列
public class isSubsequence {
/* * 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 * 你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。 *字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。 */ public boolean isSubsequence(String s, String t) {
if(0==s.length()) return true; //母串序列索引i,子串j int sub = 0,j = 0; //不能用for循环是考虑到s比t长 while( sub
< t.length()){
//如果不同只有母串后移 if(s.charAt(sub)==t.charAt(j)) sub++; j++; } //返回结果里判别是否子串全找到了,很有技巧 return sub==s.length(); }}

192.跳跃游戏

public class JumpGame {
public static boolean canJump(int[] nums){
assert nums.length>0; if(nums.length==1)return true; //数组首位为0且0不是唯一元素肯定跳不到最后 if(nums.length>1&&nums[0]==0)return false; for (int i = 1; i < nums.length-1; i++) {
int j = i - 1; while (nums[i] == 0) {
//前面两个if是找到j的情况,说明这个0元素是可以被到达或跳过的 // if (nums[j] >= i - j&&i==nums.length-1) break; if (nums[j] > i - j) break; if (j <= 0) return false; j--; } } return true; } //just for test public static void main(String[] args) {
Scanner input = new Scanner(System.in); String s = input.next(); String[] arr = s.split(","); int[] arry = new int[arr.length]; for (int i = 0; i < arr.length; i++) {
arry[i] = Integer.parseInt(arr[i]); } boolean result =canJump(arry); System.out.println(result); }}
  1. 最大子序和
import java.util.Scanner;/** * 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 * 输入[-2,1,-3,4,-1,2,1,-5,4];输出6;因为连续子数组 [4,-1,2,1] 的和最大,为 6。 */public class MaxSubarray {
public static int maxSubarray(int[] nums) {
//sum存子序和,max表示选好子序手标的某次的和 int sum = nums[0]; int max = 0; for(int i=0;i

转载地址:http://dfrsi.baihongyu.com/

你可能感兴趣的文章
自己的网站与UCenter整合(大致流程)
查看>>
laravel 制作通用的curd 后台操作
查看>>
【小红书2017年笔试】求一个数组中平均数最大的子数组
查看>>
Linux基础系列-定时器与时间管理
查看>>
Linux基础系列-可执行程序的产生过程
查看>>
Linux基础系列-Kernel 初始化宏
查看>>
Linux子系统系列-I2C
查看>>
<iOS>关于自定义description的一点用法
查看>>
Unix 命令,常用到的
查看>>
DLL中建立进程共享数据段需要注意的语法问题
查看>>
服务器端技术----Http请求的处理过程
查看>>
如何区分 const char * p, char * const p, const char * * p?
查看>>
C语言-预处理指令2-条件编译
查看>>
C语言-预处理指令3-文件包含
查看>>
C语言-变量类型
查看>>
C语言-static和extern关键字1-对函数的作用
查看>>
C 语言-static和extern关键字2-对变量的作用
查看>>
C# 学习笔记(三) ForEach遍历集合
查看>>
C# 迭代器详解
查看>>
C# 学习笔记(四) 结构体实现接口后是值类型还是引用类型
查看>>