• 算法-贪心算法


    题目:给定一个字符串str,只由‘X’和‘.’两种字符构成。‘X’表示墙,不能放灯,也不需要点亮‘.’表示居民点,可以放灯,需要点亮如果灯放在i位置,可以让i-1,i和i+1三个位置被点亮返回如果点亮str中所有需要点亮的位置,至少需要几盏灯

    思路:递归方式,每个位置两种情况,不选择或者选择(当前必须是 '.'),如果是选择,记录当前位置。边界条件为当前位置超过字符串长度,遍历整个数组,检查是否有不合规的位置,如果没有返回当前递归组合中灯个数。递归方法返回从当前位置开始直到最后位置最少灯数量

    public static int fun240808(String line){
            // PC
            if(line == null || line.length()<=0)
                return 0;
            char[] arr = line.toCharArray();
            return process240808(arr,0,new HashSet<>());
        }
        // 返回从index开始到line末尾点亮所有最少灯光
        public static int process240808(char[] line, int index, HashSet<Integer> pos){
            if(index >=line.length){
                // pos 当前递归各灯组合
                for (int i = 0; i < line.length; i++) {
                    if(line[i]  != 'X'){
                        // 当前递归组合存在未覆盖完全的场景,无效组合
                        if(!pos.contains(i-1) && !pos.contains(i)&& !pos.contains(i+1)){
                            return Integer.MAX_VALUE;
                        }
                    }
                }
                return pos.size();
            }
            int no = process240808(line,index+1,pos);
            int yes = Integer.MAX_VALUE;
            if(line[index] == '.'){
                pos.add(index);
                yes = process240808(line,index+1,pos);
                pos.remove(index);
            }
            return Math.min(yes,no);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    思路2:贪心算法

    public static int getlights(String line){
            // PC
            // cur之前及时有灯也无法覆盖cur位置,也即cur之前所有灯能覆盖位置后的第一个灯的位置
            int count = 0 ;
            for (int i = 0; i < line.length(); i++) {
                if(line.charAt(i) == '.'){
                    count++;
                    i = i+1<line.length() && line.charAt(i+1) == '.'?i+2:i+1;
                }
            }
            return count;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    一块金条切成两半,是需要花费和长度数值一样的铜板的。 比如长度为20的金条,不管怎么切,都要花费20个铜板。 一群人想整分整块金条,怎么分最省铜板? 例如,给定数组{10,20,30},代表一共三个人,整块金条长度为60,金条要分成10,20,30三个部分。 如果先把长度60的金条分成10和50,花费60; 再把长度50的金条分成20和30,花费50;一共花费110铜板。 但如果先把长度60的金条分成30和30,花费60;再把长度30金条分成10和20, 花费30;一共花费90铜板。 输入一个数组,返回分割的最小代价。

    思路:递归方式,当前数组两两组合,得到新数组以及累加和,重复递归,直到数组长度为1

    public static int fun240209(int[] arr){
            if(arr == null || arr.length<=0)
                return 0;
            return process240209(arr,0);
        }
        // pre 之前各种组合得到的金额
    	// arr 当前遍历数组
        public static int process240209(int[] arr,int pre){
            if(arr.length == 1){
                return pre;
            }
            int min = Integer.MAX_VALUE;
            for(int i = 0;i<arr.length;i++){
                for(int j = i+1;j<arr.length;j++){
                    // 递归调用合并完的数组
                    min = Math.min(min,process240209(merge240209(arr,i,j),pre+arr[i]+arr[j]));
                }
            }
            return min;
        }
    // 原有数组两两合并后得到新的数组
        public static int[] merge240209(int[] arr,int i,int j){
            int[] ans = new int[arr.length - 1];
            int index = 0;
            for (int k = 0; k < arr.length; k++) {
                if(k == j || k == i)
                    continue;
                ans[index++] = arr[k];
            }
            ans[index] = arr[i]+arr[j];
            return ans;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    思路2 哈夫曼树

    public static int fun2240209(int[] arr){
            // PC 参数校验
            if(arr == null || arr.length<=0)
                return 0;
            PriorityQueue<Integer> queue = new PriorityQueue<>();
            for (int i = 0; i < arr.length; i++) {
                queue.add(arr[i]);
            }
            int ans = 0;
            while (queue.size()>1){
                // 将最小两个数合并
                int sum = queue.poll()+queue.poll();
                ans += sum;
                queue.add(sum);
            }
            return ans;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    题目:输入: 正数数组costs、正数数组profits、正数K、正数M costs[i]表示i号项目的花费 profits[i]表示i号项目在扣除花费之后还能挣到的钱(利润) K表示你只能串行的最多做k个项目 M表示你初始的资金 说明: 每做完一个项目,马上获得的收益,可以支持你去做下一个项目。不能并行的做项目。 输出:你最后获得的最大钱数。

    思路:贪心法

    // 贪心法 当前资金能做的项目,从这些项目里面拿出收益最大的,更新当前资金,重复上面操作,直到遍历完成k次或者所有做完所有项目收益资金都无法满足
        // 剩余的项目
        public static int getMaxMoney(int K, int W, int[] Profits, int[] Capital) {
            PriorityQueue<Project> minCost = new PriorityQueue<>();
            PriorityQueue<Project> maxProfit = new PriorityQueue<>();
            // 初始化mincost
            for (int i = 0; i < Profits.length; i++) {
                minCost.add(new Project(Capital[i],Profits[i]));
            }
    
            for (int i = 0; i < K; i++) {
                while (!minCost.isEmpty() && minCost.peek().cost<=W){
                    maxProfit.add(minCost.poll());
                }
                if(maxProfit.isEmpty()){
                    return W;
                }
                W += maxProfit.poll().profit;
            }
            return W;
        }
        static class Project{
            private int cost;
            private int profit;
            public Project(int cost,int profit){
                this.cost = cost;
                this.profit = profit;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
  • 相关阅读:
    Pytorch中的梯度知识总结
    企业如何搭建自己的知识库?
    Java并发编程学习十二:死锁问题
    vue2技能树(11)-路由安装与基本配置、路由导航、嵌套路由
    TIA博途V17中ProDiag功能的使用方法示例(二)可编辑的文本框
    vscode中git拉取、提交代码、解决冲突,以及合并代码的操作
    java常用集合及常用类
    【数据仓库设计基础(三)】数据集市
    Docker-dockerfile构建镜像
    【c语言】详解文件操作(一)
  • 原文地址:https://blog.csdn.net/u014516441/article/details/136175303