贪心算法练习

贪心算法适用问题:

一.最优子结构:当一个问题的最优解包含其子问题的最优解,这是问题可以采用动态规划法或贪心法求解的关键性质。

二.具有贪心选择性质:指问题整体最优解可以由一系列局部最优解的选择得到,这是贪心法和动态规划的主要区别。

 

1. 删数问题

题目:有一个正整数n,去掉其中的s个数,使得剩下的新数最小

(解法:每次删除一个数,使剩下的数最小,重复n次即为答案)

代码:

/**
 * 贪心算法,删数问题
 */
public class Main {
	public static void main(String[] args) {
		String n = "178543";// 目标数
		int s = 2;// 要删去数的个数
		// s次贪心选择
		for (int i = 0; i < s; i++) {
			for (int j = 0; j < n.length(); j++) {
				int thisOne = n.charAt(j) - '0';
				// 如果判断的是第一个数
				if (j == 0) {
					int nextOne = n.charAt(j + 1) - '0';
					if (thisOne > nextOne) {
						n = deleteChar(n, j);
						break;
					}
					continue;
				}

				// 如果判断的是最后一个数的话
				if (j == n.length() - 1) {
					int lastOne = n.charAt(j - 1) - '0';
					if (thisOne > lastOne) {
						n = deleteChar(n, j);
						break;
					}
					continue;
				}

				// 如果是中间的某个数时
				int lastOne = n.charAt(j - 1) - '0';
				int nextOne = n.charAt(j + 1) - '0';
				if (thisOne > nextOne && thisOne > lastOne) {
					n = deleteChar(n, j);
					break;
				}
			}
		}
		System.out.println(n);
	}

	// 删除字符串中指定索引的字符
	public static String deleteChar(String string, int index) {
		return string.substring(0, index) + string.substring(index + 1);
	}
}

2.数列极差问题

题目:现有一个数列,随意删掉其中两个数a和b,然后再向数组中添加a*b+1的结果,重复此操作,直至剩最后一个数,分别求出在所有按这种操作得到的结果中,最大值Max和最小值Min,Max-Min即为极差。

解法:每次合并最小的两个数最后得到的是最大的,每次合并最大的两个数最后得到的是最小的

代码:

import java.util.Arrays;

/**
 * 贪心算法,数列极差问题
 */
public class Main {
	public static void main(String[] args) {
		int[] targetArray = { 8, 6, 5, 9, 7, 1, 9, 2, 4, 7, 9 };
		// 排个序
		Arrays.sort(targetArray);
		int max = getMax(targetArray);
		int min = getMin(targetArray);
		System.out.println(max + "-" + min + "=" + (max - min));
	}

	// 获取最小min,每次合并最大的两个数
	public static int getMin(int[] arr) {
		int[] arrCopy = Arrays.copyOf(arr, arr.length);
		int len = arr.length;

		// 合并的次数
		for (int i = 0; i < len - 1; i++) {
			int max1 = arrCopy.length - 1;
			int max2 = arrCopy.length - 2;
			arrCopy = replaceTwoNum(arrCopy, max1, max2);
		}
		return arrCopy[0];
	}

	// 获取最大max,每次合并最小的两个数
	public static int getMax(int[] arr) {
		int[] arrCopy = Arrays.copyOf(arr, arr.length);
		int len = arr.length;

		// 合并的次数
		for (int i = 0; i < len - 1; i++) {
			int min1 = 0;
			int min2 = 1;
			arrCopy = replaceTwoNum(arrCopy, min1, min2);
		}
		return arrCopy[0];
	}

	// 将数组内两个位置的数相加再加一,然后删除这两个数,并将和数添加到数组
	public static int[] replaceTwoNum(int[] arr, int i, int j) {
		int m = arr[i] * arr[j] + 1;
		int[] result = new int[arr.length - 1];
		int c = 0;
		for (int x = 0; x < arr.length; x++) {
			if (x != i && x != j)
				result[c++] = arr[x];
		}
		result[result.length - 1] = m;
		Arrays.sort(result);
		return result;
	}
}

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(算法,贪心算法)