贪心算法应用代码

字符串拼接

给定一个字符串类型的数组strs,找到一种拼接方式,使得把所有字符串拼起来之后形成的字符串具有最低的字典序。

import java.util.Arrays;
import java.util.Comparator;
public class hello {
    //定义比较器(利用字典序):a连接b跟b连接a的字符串大小比较
    public static class MyComparator implements Comparator<String> {
        @Override
        public int compare(String a, String b) {
            return (a + b).compareTo(b + a);
        }
    }

    //连接
    public static String lowestString(String[] strs) {
        if (strs == null || strs.length == 0) {
            return "";
        }
        //利用比较器排序
        Arrays.sort(strs, new MyComparator());
        //连接
        String res = "";
        for (int i = 0; i < strs.length; i++) {
            res += strs[i];
        }
        return res;
    }

    public static void main(String[] args) {
        String[] strs1 = { "jibw", "ji"};
        System.out.println(lowestString(strs1));

        String[] strs2 = { "ba", "b" };
        System.out.println(lowestString(strs2));
    }
}

结果:
jibwji
bab
注:
(1)只能比较str1.str2<=str2.str1,不可以直接比较str1<=str2
例:比较字符串b ba
字符串本身b<ba,但是连接后的字符串 bba>bab
(2)字符串连接比较具有传递性
a.b<=b.a,b.c<=c.b
可以推出a.c<=c.a

切割铜板

一块金条切成两半,是需要花费和长度数值一样的铜板的。比如长度为20的 金条,不管切成长度多大的两半,都要花费20个铜板。一群人想整分整块金 条,怎么分最省铜板? 例如,给定数组{10,20,30},代表一共三个人,整块金条长度为 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铜板。 输入一个数组,返回分割的最小代价。
方法:构造哈夫曼树
给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树。
哈夫曼树的构造:
假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为:
(1) 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点);
(2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;
(3)从森林中删除选取的两棵树,并将新树加入森林;
(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。
优先级队列
如果我们给每个元素都分配一个数字来标记其优先级,不妨设较小的数字具有较高的优先级,这样我们就可以在一个集合中访问优先级最高的元素并对其进行查找和删除操作了。优先级队列(priority queue) 是0个或多个元素的集合,每个元素都有一个优先权,对优先级队列执行的操作有(1)查找(2)插入一个新元素 (3)删除 一般情况下,查找操作用来搜索优先权最大的元素,删除操作用来删除该元素 。对于优先权相同的元素,可按先进先出次序处理或按任意优先权进行。

import java.util.PriorityQueue;
public class hello {
    //计算最少钱数
    public static int lessMoney(int[] arr) {
        PriorityQueue<Integer> pQ = new PriorityQueue<>();//优先级队列相当于堆
        for (int i = 0; i < arr.length; i++) {
            pQ.add(arr[i]);//把每个节点入堆
        }
        int sum = 0;
        int cur = 0;
        while (pQ.size() > 1) {
            //当前两个最小节点相加
            cur = pQ.poll() + pQ.poll();
            sum += cur;
            pQ.add(cur);
        }
        return sum;
    }

    public static void main(String[] args) {
        // solution
        int[] arr = { 6, 7, 8, 9 };
        System.out.println(lessMoney(arr));
    }
}

结果:60

收益最大

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


import java.util.Comparator;
import java.util.PriorityQueue;
public class hello {
    public static class Node {
        public int p;  //p是收益
        public int c;  //c是花费
        //node为项目
        public Node(int p, int c) {
            this.p = p;
            this.c = c;
        }
    }
    //最小花费比较器
    public static class MinCostComparator implements Comparator<Node> {
        @Override
        public int compare(Node o1, Node o2) {
            return o1.c - o2.c;
        }
    }
    //最大收益比较器
    public static class MaxProfitComparator implements Comparator<Node> {
        @Override
        public int compare(Node o1, Node o2) {
            return o2.p - o1.p;
        }
    }
    //寻找最大收益(k为最多做的项目,w为初始启动资金,profits为利润数组,capital为花费数组)
    public static int findMaximizedCapital(int k, int W, int[] Profits, int[] Capital) {
        Node[] nodes = new Node[Profits.length];
        //创建项目节点
        for (int i = 0; i < Profits.length; i++) {
            nodes[i] = new Node(Profits[i], Capital[i]);
        }
        //cost小根堆
        PriorityQueue<Node> minCostQ = new PriorityQueue<>(new MinCostComparator());
        //profit大根堆
        PriorityQueue<Node> maxProfitQ = new PriorityQueue<>(new MaxProfitComparator());
        //所有项目加入小根堆
        for (int i = 0; i < nodes.length; i++) {
            minCostQ.add(nodes[i]);
        }
        //要做的项目最多做k个
        for (int i = 0; i < k; i++) {
            //花费最少的小于初始启动资金,满足条件的加入profit大根堆(解锁)
            while (!minCostQ.isEmpty() && minCostQ.peek().c <= W) {
                maxProfitQ.add(minCostQ.poll());
            }
            //做不到k个项目就提前终止
            if (maxProfitQ.isEmpty()) {
                return W;
            }
            W += maxProfitQ.poll().p;
        }
        return W;
    }
}

宣讲场次

一些项目要占用一个会议室宣讲,会议室不能同时容纳两个项目的宣讲。 给你每一个项目开始的时间和结束的时间(给你一个数组,里面 是一个个具体的项目),你来安排宣讲的日程,要求会议室进行 的宣讲的场次最多。返回这个最多的宣讲场次。
方法:按结束时间早晚排,早结束优先。

import java.util.Arrays;
import java.util.Comparator;
public class hello {
    public static class Program {
        public int start;//开始时间
        public int end;//结束时间

        public Program(int start, int end) {
            this.start = start;
            this.end = end;
        }
    }
    //比较器:比较结束时间早
    public static class ProgramComparator implements Comparator<Program> {
        @Override
        public int compare(Program o1, Program o2) {
            return o1.end - o2.end;
        }

    }
    //宣讲场次最好安排
    public static int bestArrange(Program[] programs, int start) {
        Arrays.sort(programs, new ProgramComparator());
        int result = 0;
        for (int i = 0; i < programs.length; i++) {
            //开始时间小于上一个的结束时间
            if (start <= programs[i].start) {
                result++;
                start = programs[i].end;
            }
        }
        return result;
    }

    public static void main(String[] args) {

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、实验目的: 掌握分页式存储管理的基本概念和实现方法。要求编写一个模拟的分页式管理程序, 并能对分页式存储的页面置换算法进行编写和计算各个算法的缺页率。 二、程序设计: 假定一个能够存放M个页面的内存,当发生缺页时,调入一个页面, 通过LRU算法求出应该置换出的页面号。输入一连串的页面号, 程序自动选择调出的页面并计算缺页率。 设计页面置换算法,这里采用最近最久未使用置换算法LRU。 LRU算法的实现要归功于一个8位的寄存器的实现。 三、算法说明: 执行程序时,当主存没有可用页面时,为了选择淘汰主存中的哪一页面, 腾出1个空闲块以便存放新调入的页面。淘汰哪个页面的首要问题是选择何种置换算法。 该程序采用LRU方法选择,依置换策略选择一个可置换的页面并计算它们的缺页率以便比较。 */ #include<iostream> using namespace std; #define M 3 #include<math.h> int reg[2][M]; int count; int num; int N; /********初始化函数,数组reg[0][i]存放页面号,初始化为-1,reg[1][i]当作寄存器, 初始化为0*********/ void init() { int i,count=0;num=0; N=(int)pow(2,7); /********二进制数10000000**********/ for(i=0;i<M;i++) { reg[0][i]=-1; reg[1][i]=0; } } /*********寻找数组a中的最小值,返回最小值对应的下标***********/ int min(int a[]) { int i,index=0; int min=a[0]; for(i=1;i<M;i++) { if(min>a[i]) { min=a[i]; index=i; } } return index; } /***判断页面号x是否在数组中,如果在,返回对应的下标;否则返回-1***/ int isIn(int x,int a[]){ int i; int index=-1; for(i=0;i<M;i++) { if(a[i]==x) { index=i; break; } } return index; } /**********判断虚拟的内存中是否已经存满了页面,如果满了,则返回-1, 没有满则返回找到空的对应的第一个下标**************/ int isFull(int a[]) { int i,index=-1; for(i=0;i<M;i++) { if(a[i]==-1) { index=i; break; } } return index; } /*************页面置换方法*****************/ void swap(int x) { int i,k,temp,temp0,count; int index=isIn(x,reg[0]); /****判断x是否在reg[0]数组中*******/ if(index!=-1) { reg[1][index]=reg[1][index]^N; }/**reg[1][index]异或二进制数10000000**/ else{ temp=isFull(reg[0]); if(temp!=-1) /*******内存没有满,直接调入页面************/ { reg[0][temp]=x; reg[1][temp]=reg[1][temp]^N; } else if(temp==-1) { k=min(reg[1]); /**置换出寄存器中数值最小的对应的下标的页面***/ temp0=reg[0][k]; /*********临时保留要换出的页面号*****/ reg[0][k]=x; reg[1][k]=reg[1][k]^N; printf("the page %d is exchanged out!\n",temp0); /******打印要置换出的页号**************/ count++; /*********置换次数加1**************/ } } for(i=0;i<M;i++) { reg[1][i]=reg[1][i]>>1; }/********寄存器中的所有数右移一位*****/ /***************打印缺页数和缺页率**********************/ printf("the count of Exchanged is: %d \n",count); printf("the rate of exchanged is: %f\n",count*1.0/num); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值