算法设计思想
贪心法的基本思想是逐步获得最优解。贪心法在求解最优解的问题时,从最初阶段开始,每一个阶段总是做一个局部最优的贪心选择,不断将问题转化成规模最小的子问题。因此,贪心法并不是从整体最优考虑,它只是在某种程度上的局部最优解。
贪心法有两个最重要的性质:
1.最优子结构的性质:当一个问题的最优解包含子问题的最优解时,称此问题有最优子结构。
2.贪心选择性质
典型例题
一、找零钱问题
某单位给每个员工发工资。为了确保不要临时兑换零钱,且取款的张数最少,取工资前要统计所有员工的工资所需要的各种币值的张数。
import java.util.Scanner;
public class ChangeMoney {
public static void main(String[] args) {
System.out.println("请输入员工工资--以0结束:");
Scanner scanner = new Scanner(System.in);
Boolean isFlag = true;
int arr[] = new int[] { 0, 100, 50, 20, 10, 5, 2, 1 };
int array[] = new int[] { 0, 0, 0, 0, 0, 0, 0, 0 };
while (isFlag) {
int num = scanner.nextInt();
if (num == 0)
isFlag = false;
for (int i = 1; i <= 7; i++) {
int A = num / arr[i];
array[i] += A;
num -= A * arr[i];
}
}
for (int i = 1; i <= 7; i++) {
System.out.printf("%d------%d\n", arr[i], array[i]);
}
}
}
算法优化
import java.util.Scanner;
public class ChangeMoney2 {
public static void main(String[] args) {
change();
}
private static void change() {
System.out.println("请输入员工工资--以0结束:");
Scanner scanner = new Scanner(System.in);
Boolean isFlag = true;
int array[] = new int[] { 0, 0, 0, 0, 0, 0, 0 };
while (isFlag) {
int num = scanner.nextInt();
if (num == 0)
isFlag = false;
array[0] += num / 100;
num %= 100;
array[1] += num / 50;
num %= 50;
array[2] += num / 20;
num %= 20;
array[3] += num / 10;
num %= 10;
array[4] += num / 5;
num %= 5;
array[5] += num / 2;
num %= 2;
array[6] += num;
}
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
二、最优装载
有一批集装箱要装上一艘载重量为c的货轮,其中集装箱的重量为w,要求装载体积不受限制的情况下,尽可能的多的集装箱装到货轮上。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
public class Huolun {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("输入集装箱的个数:");
int num = scanner.nextInt();
System.out.println("输入最大载重量:");
int max = scanner.nextInt();
System.out.println("逐个输入集装箱的重量:");
List<Integer> list = new ArrayList<Integer>();
for (int i = 1; i <= num; i++) {
int number = scanner.nextInt();
list.add(number);
}
Collections.sort(list);
int count=0;
for (int i = 0; i <num; i++) {
count+=list.get(i);
if (count>= max) {
for (int j = 0; j <= i-1; j++) {
System.out.println(list.get(j));
}
return;
}
}
}
}
三、哈夫曼编码
import java.util.Scanner;
public class HuffManCode {
//建立数的节点类
static class Node{
int weight;//频数
int parent;
int leftChild;
int rightChild;
public Node(int weight,int parent,int leftChild,int rightChild){
this.weight=weight;
this.parent=parent;
this.leftChild=leftChild;
this.rightChild=rightChild;
}
void setWeight(int weight){
this.weight=weight;
}
void setParent(int parent){
this.parent=parent;
}
void setLeftChild(int leftChild){
this.leftChild=leftChild;
}
void setRightChild(int rightChild){
this.rightChild=rightChild;
}
int getWeight(){
return weight;
}
int getParent(){
return parent;
}
int getLeftChild(){
return leftChild;
}
int getRightChild(){
return rightChild;
}
}
//新建哈夫曼编码
static class NodeCode{
String character;
String code;
NodeCode(String character,String code){
this.character=character;
this.code=code;
}
NodeCode(String code){
this.code= code;
}
void setCharacter(String character){
this.character=character;
}
void setCode(String code){
this.code=code;
}
String getCharacter(){
return character;
}
String getCode(){
return code;
}
}
//初始化一个huffuman树
public static void initHuffmanTree(Node[] huffmanTree,int m){
for(int i=0;i<m;i++){
huffmanTree[i] = new Node(0,-1,-1,-1);
}
}
//初始化一个huffmanCode
public static void initHuffmanCode(NodeCode[] huffmanCode,int n){
for(int i=0;i<n;i++){
huffmanCode[i]=new NodeCode("","");
}
}
//获取huffmanCode的符号
public static void getHuffmanCode(NodeCode[] huffmanCode , int n){
Scanner input = new Scanner(System.in);
for(int i=0;i<n;i++){
String temp = input.next();
huffmanCode[i] = new NodeCode(temp,"");
}
}
//获取huffman树节点频数
public static void getHuffmanWeight(Node[] huffmanTree , int n){
Scanner input = new Scanner(System.in);
for(int i=0;i<n;i++){
int temp = input.nextInt();
huffmanTree[i] = new Node(temp,-1,-1,-1);
}
}
//从n个结点中选取最小的两个结点
public static int[] selectMin(Node[] huffmanTree ,int n)
{
int min[] = new int[2];
class TempNode
{
int newWeight;//存储权
int place;//存储该结点所在的位置
TempNode(int newWeight,int place){
this.newWeight=newWeight;
this.place=place;
}
void setNewWeight(int newWeight){
this.newWeight=newWeight;
}
void setPlace(int place){
this.place=place;
}
int getNewWeight(){
return newWeight;
}
int getPlace(){
return place;
}
}
TempNode[] tempTree=new TempNode[n];
//将huffmanTree中没有双亲的结点存储到tempTree中
int i=0,j=0;
for(i=0;i<n;i++)
{
if(huffmanTree[i].getParent()==-1&& huffmanTree[i].getWeight()!=0)
{
tempTree[j]= new TempNode(huffmanTree[i].getWeight(),i);
j++;
}
}
int m1,m2;
m1=m2=0;
for(i=0;i<j;i++)
{
if(tempTree[i].getNewWeight()<tempTree[m1].getNewWeight())//此处不让取到相等,是因为结点中有相同权值的时候,m1取最前的
m1=i;
}
for(i=0;i<j;i++)
{
if(m1==m2)
m2++;//当m1在第一个位置的时候,m2向后移一位
if(tempTree[i].getNewWeight()<=tempTree[m2].getNewWeight()&& i!=m1)//此处取到相等,是让在结点中有相同的权值的时候,
//m2取最后的那个。
m2=i;
}
min[0]=tempTree[m1].getPlace();
min[1]=tempTree[m2].getPlace();
return min;
}
//创建huffmanTree
public static void createHaffmanTree(Node[] huffmanTree,int n){
if(n<=1)
System.out.println("Parameter Error!");
int m = 2*n-1;
//initHuffmanTree(huffmanTree,m);
for(int i=n;i<m;i++)
{
int[] min=selectMin(huffmanTree,i);
int min1=min[0];
int min2=min[1];
huffmanTree[min1].setParent(i);
huffmanTree[min2].setParent(i);
huffmanTree[i].setLeftChild(min1);
huffmanTree[i].setRightChild(min2);
huffmanTree[i].setWeight(huffmanTree[min1].getWeight()+ huffmanTree[min2].getWeight());
}
}
//创建huffmanCode
public static void createHaffmanCode(Node[] huffmanTree,NodeCode[] huffmanCode,int n){
Scanner input = new Scanner(System.in);
char[] code = new char[10];
int start;
int c;
int parent;
int temp;
code[n-1]='0';
for(int i=0;i<n;i++)
{
StringBuffer stringBuffer = new StringBuffer();
start=n-1;
c=i;
while( (parent=huffmanTree[c].getParent()) >=0 )
{
start--;
code[start]=((huffmanTree[parent].getLeftChild()==c)?'0':'1');
c=parent;
}
for(;start<n-1;start++){
stringBuffer.append(code[start]);
}
huffmanCode[i].setCode(stringBuffer.toString());
}
}
//输出hufmanCode
public static void ouputHaffmanCode(NodeCode[] huffmanCode,int n){
System.out.println("字符与编码的对应关系如下:");
for(int i=0;i<n;i++){
System.out.println(huffmanCode[i].getCharacter()+":"+huffmanCode[i].getCode());
}
}
//主函数
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int n;
int m;
System.out.print("请输入字符个数:");
n = input.nextInt();
m=2*n-1;
Node[] huffmanTree = new Node[m];
NodeCode[] huffmanCode = new NodeCode[n];
//初始化huffmanTree,huffmanCode
initHuffmanTree(huffmanTree,m);
initHuffmanCode(huffmanCode,n);
//获取huffmanCode的符号
System.out.print("请输入哈夫曼编码的字符:");
getHuffmanCode(huffmanCode,n);
//获取huffmanTree的频数
System.out.print("请输入哈夫曼编码字符对应的频数:");
getHuffmanWeight(huffmanTree,n);
//创建huffmanTree
createHaffmanTree(huffmanTree,n);
//创建huffmanCode
createHaffmanCode(huffmanTree,huffmanCode,n);
//输出huffmanCode编码
ouputHaffmanCode(huffmanCode,n);
}
}