首页 > 编程语言 >2023-04-24 算法面试中常见的贪心算法问题

2023-04-24 算法面试中常见的贪心算法问题

时间:2023-04-24 23:47:36浏览次数:57  
标签:24 04 int memo 算法 区间 intervalList 贪心

贪心算法

1 贪心选择例题

455.饼干分配

假设你想给小朋友们饼干。每个小朋友最多能够给一块儿饼干。每个小朋友都有一个“贪心指数”,称为g(i),g(i)表示的是这名小朋友需要的饼干大小的最小值。同时,每个饼干都有一个大小值s(i)。如果s(j) >= g(i),我们将饼干j分给小朋友i后,小朋友就会很开心。给定数组s和g,问如何分配饼干,能更让最多的小朋友开心。
如 g = [1, 2, 3], s = [1, 1],结果为1
如 g = [1, 2], s = [1, 2, 3],结果为2

代码见455. 分发饼干

class Solution {
    public int findContentChildren(int[] g, int[] s) {
        Arrays.sort(g);
        Arrays.sort(s);
        int gi = g.length - 1;
        int si = s.length - 1;
        int res = 0;
        while (gi >= 0 && si >= 0) {
            if (s[si] >= g[gi]) {
                si--;
                gi--;
                res++;
            } else {
                gi--;
            }
        }
        return res;
    }
}

392.判断子序列

class Solution {
    public boolean isSubsequence(String s, String t) {
        int si = 0, ti = 0;
        while (si < s.length() && ti < t.length()) {
            if (s.charAt(si) == t.charAt(ti)) {
                si++;
                ti++;
            } else {
                ti++;
            }
        }
        return si == s.length();
    }
}

2 贪心算法与动态规划的关系

每次选择中,每个区间的结尾很重要,结尾越小,留给了后面越大的空间,后面越有可能容纳更多空间区间

依据上面的思想,设计出地贪心算法如下:
按照区间的结尾排序,每次选择结尾最早地、且和前一个区间不重叠的区间

动态规划实现

参考最长上升子序列问题的求解

LIS(i) = max( 1 + LIS(j) if nums[i] > nums[j] )
         j<i

上面表达式的含义:从i处往前遍历,遍历到的位置下标为j(j<i),如果nums[j]小于nums[i],且LIS[j]的值不小于LIS[i],则把LIS[i]的值更新为LIS[j]+1,否则保持LIS[i]的值不变,核心伪代码如下:

// 第1个元素不用考虑了,其最长子序列一定是1,已经初始化好了
for (int i = 1; i < nums.length; i++) {
    for (int j = 0; j < i; j++) {
        if (nums[j] < nums[i]) {
            // 如果i前面的值有大于i处的值的,更新子序列长度
            // memo[i]表示当前i处的子序列长度,1+memo[i]表示考虑j的情况下最长子序列长度加1
            // memo[i]在 `j in 0~i`的循环中可能已经被跟新多次了,不再是初始值1了
            memo[i] = Math.max(memo[i], 1 + memo[j]);
        }
    }
}

完整实现如下:

class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        // 先转换成List,注意每个interval都是个只有俩元素的数组
        List<int[]> intervalList = new ArrayList<>(Arrays.asList(intervals));
        // 自定义比较器,先比较开头,谁大谁靠后,开头相等地话就看结尾,谁大谁靠后
        intervalList.sort((interval1, interval2) -> {
            if (interval1[0] != interval2[0]) {
                return interval1[0] - interval2[0];
            }
            return interval1[1] - interval2[1];
        });
        // 借鉴最长公共子序列的思想.
        // memo[i]表示用使用intervals[0...i]的区间能构成的最长不重叠区间序列
        int[] memo = new int[intervalList.size()];
        Arrays.fill(memo, 1);
        for (int i = 1; i < intervals.length; i++) {
            for (int j = 0; j < i; j++) {
                // 从i向前遍历,如果i前面找到一个区间的尾部比i所在的区间头部还小,说明找到了一个不重叠区间
                if (intervalList.get(i)[0] >= intervalList.get(j)[1]) {
                    memo[i] = Math.max(memo[i], 1 + memo[j]);
                }
            }
        }
        // 取出最大的不重叠子区间个数
        int res = 0;
        for (int num : memo) {
            if (num > res) {
                res = num;
            }
        }
        // 题目要地是删除多少个区间可以得到最大的不重叠的子区间,所以要用区间总个数减去最多的不重叠子区间个数
        return intervalList.size() - res;
    }
}

贪心算法实现

每次选择结尾最早地、且和前一个区间不重叠的区间

class 贪心算法实现 {
    public int eraseOverlapIntervals(int[][] intervals) {
        if(intervals.length == 0){
            return 0;
        }
        // 先转换成List,注意每个interval都是个只有俩元素的数组
        List<int[]> intervalList = new ArrayList<>(Arrays.asList(intervals));
        // 自定义比较器,先比较结尾,谁大谁靠后,结尾相等地话就看开头,谁大谁靠后
        intervalList.sort((interval1, interval2) -> {
            if (interval1[1] != interval2[1]) {
                return interval1[1] - interval2[1];
            }
            return interval1[0] - interval2[0];
        });
        // 贪心算法思路:不断选取结尾最早且区间和前面不重合的区间
        // 第一个区间先选上
        int res=1;
        // i前面的区间在intervalList中的下标
        int pre = 0;
        for (int i = 1; i < intervalList.size(); i++) {
            // 前面区间的结尾比后面区间的开头还小,说明找到了一个不重叠区间
            if (intervalList.get(pre)[1] <= intervalList.get(i)[0]){
                res++;
                pre = i;
            }
        }
        return intervalList.size() - res;
    }
}

3 贪心选择的适用性验证与性质

验证问题是否能用贪心算法:反证法

贪心算法的每个步骤不能影响后面的步骤,看问题是否适用于贪心算法可以尝试能否举出返利说明贪心算法中间步骤的错误性。下面就是举反例证明当前问题贪心算法是否适用的例子
![举反例证明当前问题贪心算举反例证明当前问题贪心算法是否适用例,如何验证问题能否用贪心算法?
使用归纳法:假设贪心算法不正确,不断向后推导,如果能推导出和已知矛盾的结论,就说明贪心算法是适用地

贪心算法的性质

给定一组区间,问最多保留多少个区间,可以让这些区间之间互相不重叠。

贪心算法:按照区间的结尾排序,每次选择结尾最早的,且和前一个区间不重叠的区间
某次选择的是 [s(i), f(i)];其中f(i)是当前所有选择中结尾最早的

假设这个选择不是最优的。也就是说,如果这个问题的最优解为k,则这个选择得到的解,最多为k-1。
假设最优解在这一步选择 [s(j), f(j)] 中,f(j) > f(i)。
此时,显然可以将[s(i), f(i)]替换[s(j),f(j)],而不影响后续的区间选择。
![贪心算法的性质](src贪心算法的性质sr贪心算法的性质2质证明

![贪心算法的性质证明](s贪心算法的性质证明

标签:24,04,int,memo,算法,区间,intervalList,贪心
From: https://www.cnblogs.com/lsgwr/p/17351314.html

相关文章

  • 2023/4/24
    L1-003个位数统计分数 15全屏浏览题目作者 陈越单位 浙江大学给定一个 k 位整数 N=dk−1​10k−1+⋯+d1​101+d0​ (0≤di​≤9, i=0,⋯,k−1, dk−1​>0),请编写程序统计每种不同的个位数字出现的次数。例如:给定 N=100311,则有2个0,3个1,和......
  • 4.24总结
    --基础查询--1.查询多个字段/*1.查询多个字段SELECT字段列表FROM表名;SELECT*FROM表名;--查询所有数据去除重复记录SELECTDISTINCT字段列表FROM表名;3.起别名AS:AS也可以省略*/droptableifexistsstu;CREATETABLEstu(idint,namevarchar(20),......
  • 2023.4.24记录
    声明抽象基类Shape,由它派生出三个类,圆形Circle,矩形Rectangle,三角形Triangle,用一个函数输出三个面积。输入格式:在一行中依次输入5个数,圆的半径,长方形的高和宽,三角形的高和底,中间用空格分隔输出格式:圆的面积,长方形的面积,三角形的面积,小数点后保留2位有效数字,每个面积占一行。......
  • 2023.4.24
     1//实验五任务二2#include<iostream>3usingnamespacestd;4classvector3D5{6private:7floatx,y,z;8public:9vector3D()10{11x=0;12y=0;13z=0;14}15friendostream&oper......
  • day55(2023.4.24)
    1.应用程序分层 应用程序分层实现在分层项目中实现查询业务UserDao接口 UserDaoImpl接口实现类 UserService接口 UserServiceImpl接口实现类 web 此时数据库中的数据 运行结果2.封装通用的BaseDao封装通用的DML操作BaseDao接口 BaseDaoImpl接......
  • Codeforces 1804G - Flow Control(势能分析)
    成功把这道小清新题做成了一道大数据结构题,我的评价是我是小丑。首先显然要离散化对时间轴扫描线。这个除以\(2\)下取整的操作显然启示我们往势能的方向思考,也就是我们希望能够找到某个变量,使得这个变量的均摊变化次数在可接受范围内。但是直接以每个元素的值为势能好像也不太......
  • 4.24
    1#include<iostream>2usingnamespacestd;3classDataType4{5public:6DataType(inti)7{8data.i=i;9type=INT;10}11DataType(charc)12{13data.c=c;14type=CHAR;1......
  • 基于Astar算法的智能避障最短路径搜索matlab仿真,可以任意选择起点和终点
    1.算法仿真效果matlab2022a仿真结果如下:2.算法涉及理论知识概要Astar算法是一种图形搜索算法,常用于寻路。它是个以广度优先搜索为基础,集Dijkstra算法与最佳优先(bestfit)算法特点于一身的一种算法。它通过下面这个函数来计算每个节点的优先级,然后选择优先级最高的节点作为......
  • 基于互信息和归一化互信息的医学图像配准算法matlab仿真
    1.算法仿真效果matlab2022a仿真结果如下:2.算法涉及理论知识概要信息论中将互信息定义为信息之间的关系,可以表示为两个随机变量之间统计相关性的度量,由此可以得出图像互信息的计算方法。作为图像多模态配准中的度量,图像互信息利用对图像灰度值的统计数据形成单个图像的灰度值概......
  • 基于互信息和归一化互信息的医学图像配准算法matlab仿真
    1.算法仿真效果matlab2022a仿真结果如下:      2.算法涉及理论知识概要       信息论中将互信息定义为信息之间的关系,可以表示为两个随机变量之间统计相关性的度量,由此可以得出图像互信息的计算方法。作为图像多模态配准中的度量,图像互信息利用对图像灰......