贪心问题(算法)

贪心算法简介

贪心算法的本质就是选择每一个阶段的局部最优,从而达到全局最优 。

贪心算法的一般解题步骤

贪心算法一般分为四个步骤

  • 将问题分解为若干个子问题
  • 找出合适的贪心策略
  • 求解每一个子问题的最优解
  • 将每个子问题的全局最优解堆叠为全局最优解

饼干问题

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
示例 1:
输入: g = [1,2,3], s = [1,1]
输出: 1 解释:你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。所以你应该输出1。

分析

贪心算法的本质就是要将问题分割为一个个的小问题,饼干问题的分割就是要将整个的问题细分,具体要怎么细分,将满足每个孩子的胃口看作一个子问题。
这里的局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩。

 public static int findContentChildren(int[] g,int[] s)
    {
        Arrays.sort(g);   // 饼干
        Arrays.sort(s) ;  // 胃口
        int start = 0 ;
        int count = 0 ;
        for(int i = 0 ; i< s.length ; i++ )
        {
            if(start >= g.length)
            {
                break ;
            }
            if(s[i]>= g[start])
            {
                start++ ;
                count++ ;
            }
        }
        return count ;
    }

摆动序列

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。
例如, [1,7,4,9,2,5] 是一个摆动序列,因为差值 (6,-3,5,-7,3) 是正负交替出现的。相反, [1,4,7,2,5] 和 [1,7,4,5,5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。
给定一个整数序列,返回作为摆动序列的最长子序列的长度。 通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。
示例 1:
输入: [1,7,4,9,2,5]
输出: 6
解释: 整个序列均为摆动序列。

思路

摆动序列的问题在于要尽可能多的局部峰值。什么是局部峰值,就是在一段升序序列中的最大值最小值。
那么这道问题可以将整体最优(整个序列中有最多的局部峰值)
局部最优,删除单调坡度上的节点,那么整个坡度就有两个局部的峰值,。也可不删

public static  int wiggleMax(int [] arr)
   {
       if(arr.length<=1)
       {
           return arr.length ;
       }
       int curdif = 0 ;
       int predif = 0 ;
       int result = 1 ;
       for(int i = 0 ; i< arr.length-1 ; i++)
       {
           curdif = arr[i+1]-arr[i] ;
           if((curdif>0 && predif <= 0)||((curdif<0 && predif >= 0)))
           {
               result++ ;
               predif =curdif ;
           }
       }
       return result ;
   }

   public static void main(String[] args) {
       int[] arr = {1,7,4,9,2,5} ;

       System.out.println(wiggleMax(arr));
   }

买卖股票的最佳时机

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入: [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4。随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。

贪心算法

假如第0天买入,第3天卖出,那么利润为:prices[3] - prices[0]。
相当于(prices[3] - prices[2]) + (prices[2] - prices[1]) + (prices[1] - prices[0])。
此时就是把利润分解为每天为单位的维度,而不是从0天到第3天整体去考虑!

  public static int maxProfile(int[] prices)
    {
        int max_pro  = 0 ;
        for(int i = 1 ; i< prices.length ; i++)
        {
            int temp = prices[i]-prices[i-1] ;
            if(temp > 0 )
            {
                max_pro+=temp;
            }
        }
        return max_pro ;
    }
    public static void main(String[] args) {
        int prices[] = {1,2,3,4,5} ;
        System.out.println(maxProfile(prices));
    }

跳跃游戏

给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个位置。
示例 1:
输入: [2,3,1,1,4]
输出: true
解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。

思路

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值