leetcode算法题解(Java版)-11-贪心大法

简介: 多了一个条件,就是有重复数字出现。那可以考虑先排序,然后递归选择在相应位置放置数字的时候,可以添加判断是否被用过,也就是和前面那个比较一下:如果前面那个数和它一样值,而且目前的used 显示false那说明这个数已经在这个位置被用过了,而且已经计入了结果res中。

一、全排列变式(递归)

题目描述

Given a collection of numbers that might contain duplicates, return all possible unique permutations.
For example,
[1,1,2]have the following unique permutations:
[1,1,2],[1,2,1], and[2,1,1].

思路

  • 多了一个条件,就是有重复数字出现。那可以考虑先排序,然后递归选择在相应位置放置数字的时候,可以添加判断是否被用过,也就是和前面那个比较一下:如果前面那个数和它一样值,而且目前的used 显示false那说明这个数已经在这个位置被用过了,而且已经计入了结果res中。

代码

import java.util.ArrayList;
import java.util.Arrays;

public class Solution {
    public ArrayList<ArrayList<Integer>> permuteUnique(int[] num) {
        ArrayList<ArrayList<Integer>> res=new ArrayList<>();
        int len=num.length;
        if(num==null||len==0){
            return res;
        }
        boolean [] used=new boolean[len];
        ArrayList<Integer> list=new ArrayList<>();
        Arrays.sort(num);
        dfs(list,num,used,res);
        return res;
    }
    
    public void dfs(ArrayList<Integer> list,int [] num,boolean [] used,ArrayList<ArrayList<Integer>> res){
        if(list.size()==num.length){
            res.add(new ArrayList<Integer>(list));
            return ;
        }
        for(int i=0;i<num.length;i++){
            if(i>0&&num[i]==num[i-1]&&!used[i-1]){//如果它前一个和它一样的数现在没有被用过,那就跳过,
                //说明之前那个数已经形成过结果list之一了,目前这个分支处于回溯阶段。。。有点绕,希望能明白
                continue;
            }
            if(!used[i]){
                used[i]=true;
                list.add(num[i]);
                dfs(list,num,used,res);
                list.remove(list.size()-1);
                used[i]=false;
            }
        }
    }
}

二、贪心

题目描述

Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Determine if you are able to reach the last index.
For example:
A =[2,3,1,1,4], returntrue.
A =[3,2,1,0,4], returnfalse

思路

  • 贪心的题,每走一步,跟新一下从当前这个位置所能到达的最大距离。这就是这题的贪心,贪心一般证明很难,但是可以逻辑简单想一下,肯定是能走的距离越大越好,越有可能到达终点,再说,如果最大距离都不能到终点,那其他情况更加不可能了。

代码

public class Solution {
    public boolean canJump(int[] A) {
        int maxlen=A[0];
        for(int i=1;i<A.length;i++){
            if(maxlen==0){
                return false;
            }
            maxlen-=1;
            maxlen=Math.max(maxlen,A[i]);
            //if(maxlen+i==A.length-1){//剪枝
            //    return true;
           // }
        }
        return true;
    }
}

三、动态规划or贪心

题目描述

Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Your goal is to reach the last index in the minimum number of jumps.
For example:
Given array A =[2,3,1,1,4]
The minimum number of jumps to reach the last index is2. (Jump1step from index 0 to 1, then3steps to the last index

思路

  • dp解法:
  • 题目想考察的是贪心,想了一下,思绪有点乱。先看一下动态规划的解法。
  • 首先,满足dp的条件:1.子问题的最优解也是全局的最优解,有最优子结构;2.当前状态只依赖于它上一个状态,与怎么到达它上一个状态的路径无关。

代码

public class Solution {
    public int jump(int[] A) {
        int [] dp=new int[A.length];//存放起点到各点的最小步数
        for(int i=0;i<A.length;i++){
            int maxpos=Math.min(i+A[i],A.length-1);
            for(int j=i+1;j<=maxpos;j++){
                if(dp[j]==0){
                    dp[j]=dp[i]+1;
                }
            }
            if(dp[A.length-1]!=0){
                break;
            }
        }
        return dp[A.length-1];
    }
}

思路二

  • 贪心解法:
  • 贪心大法好,但真的难想明白。。首先,要设置三个值:当前位置(是一个区域:从i~furthest_pre中,区域中的点中能到达的最大位置)所能到达的最大位置(furthest_cur),当前位置的上一个位置(也是区域)所能到达的最大位置(furthest_pre),还有就是所走的步数。
  • 有一点可能有点会懵,furthest_cur是还没有step++的时候,具体结合代码,也就是是一个预判能走到的但还没走的状态。
  • 感觉讲的还是有点乱,现在抛开代码,想象我们站在题目给的数组的开头位置:从开始位置到开始位置能走到的最大距离(furthest_pre)之间构成了一块区域,然后我们开始一格一格走,每走一下刷新一下当前这块区域能到的最大位置(furthest_cur),如果走到从开始位置走到了furthest_pre那我们也刷新出了最大的furthest_cur,如果furthest_cur比终点大,那恭喜!再跳一不就到终点了!可以开始跳一步咯!然后重复上述的动作,直到到达终点。
  • 如果能一步到最大位置furthest_pre,那肯定能到一步到它前面那块区域的某一位置,实行下一步跳,跳到furthest_cur
  • 给一个测试用例,可以在纸上画画:
4 1 6 9 7 4 5 0 6 8 1 2 3 5 8 0 2 1 2

代码

public class Solution {
    public int jump(int[] A) {
        int len=A.length;
        if(len==0||A==null){
            return 0;
        }
        int furthest_cur=0;
        int furthest_pre=0;
        int steps=0;
        for(int i=0;i<len;i++){
            if(furthest_pre>=len){
                return steps;
            }
            if(i>furthest_pre){
                furthest_pre=furthest_cur;
                steps++;
            }
            furthest_cur=Math.max(furthest_cur,A[i]+i);
        }
        return steps;
    }
}
目录
相关文章
|
8天前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
34 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
18天前
|
算法
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
36 0
|
5天前
|
算法
每日一道算法题(Leetcode 20)
每日一道算法题(Leetcode 20)
15 2
|
10天前
|
算法 搜索推荐 Java
java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题
这篇文章介绍了如何使用Java后端技术,结合Graphics2D和Echarts等工具,生成包含个性化信息和图表的海报,并提供了详细的代码实现和GitHub项目链接。
30 0
java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题
|
14天前
|
算法 Java 数据中心
探讨面试常见问题雪花算法、时钟回拨问题,java中优雅的实现方式
【10月更文挑战第2天】在大数据量系统中,分布式ID生成是一个关键问题。为了保证在分布式环境下生成的ID唯一、有序且高效,业界提出了多种解决方案,其中雪花算法(Snowflake Algorithm)是一种广泛应用的分布式ID生成算法。本文将详细介绍雪花算法的原理、实现及其处理时钟回拨问题的方法,并提供Java代码示例。
34 2
|
10天前
|
算法 Java Linux
java制作海报一:java使用Graphics2D 在图片上写字,文字换行算法详解
这篇文章介绍了如何在Java中使用Graphics2D在图片上绘制文字,并实现自动换行的功能。
28 0
|
13天前
|
算法 Java
LeetCode(一)Java
LeetCode(一)Java
|
18天前
|
算法 Java 测试技术
数据结构 —— Java自定义代码实现顺序表,包含测试用例以及ArrayList的使用以及相关算法题
文章详细介绍了如何用Java自定义实现一个顺序表类,包括插入、删除、获取数据元素、求数据个数等功能,并对顺序表进行了测试,最后还提及了Java中自带的顺序表实现类ArrayList。
12 0
|
2月前
|
算法
测试工程师的技能升级:LeetCode算法挑战与职业成长
这篇文章通过作者亲身体验LeetCode算法题的过程,探讨了测试工程师学习算法的重要性,并强调了算法技能对于测试职业成长的必要性。
57 1
测试工程师的技能升级:LeetCode算法挑战与职业成长
|
2月前
|
设计模式 缓存 算法
揭秘策略模式:如何用Java设计模式轻松切换算法?
【8月更文挑战第30天】设计模式是解决软件开发中特定问题的可重用方案。其中,策略模式是一种常用的行为型模式,允许在运行时选择算法行为。它通过定义一系列可互换的算法来封装具体的实现,使算法的变化与客户端分离。例如,在电商系统中,可以通过定义 `DiscountStrategy` 接口和多种折扣策略类(如 `FidelityDiscount`、`BulkDiscount` 和 `NoDiscount`),在运行时动态切换不同的折扣逻辑。这样,`ShoppingCart` 类无需关心具体折扣计算细节,只需设置不同的策略即可实现灵活的价格计算,符合开闭原则并提高代码的可维护性和扩展性。
56 2