贪心算法-数列极差问题-JAVA

贪心算法-数列极差问题

【题目描述】 

 在黑板上写了N个正整数做成的一个数列,进行如下操作:每一次擦去其中的两个数a和b,然后在数列中加入一个数a×b+1,如此下去直至黑板上剩下一个数,在所有按这种操作方式最后得到的数中,最大的max,最小的为min,则该数列的极差定义为M=max-min。

编程任务:对于给定的数列,编程计算出极差M。

输入输出样例:

输入:                    

4

2 1 4 3

输出:

13

【算法分析】

当看到此题时,我们会发现求max与求min是两个相似的过程。若我们把求解max与min的过程分开,着重探讨求max的问题。

下面我们以求max为例来讨论此题用贪心策略求解的合理性。

讨论:假设经(N-3)次变换后得到3个数:a ,b , max'(max'≥a≥b),其中max'是(N-2)个数经(N-3)次f变换后所得的最大值,此时有两种求值方式,设其所求值分别为 z1,z2,则有:z1=(a×b+1)×max'+1,z2=(a×max'+1)×b+1所以z1-z2=max'-b≥0若经(N-2)次变换后所得的3个数为:m,a,b(m≥a≥b)且m不为(N-2)次变换后的最大值,即m<max'则此时所求得的最大值为:

z3=(a×b+1)×m+1此时z1-z3=(1+ab)(max'-m)>0 所以此时不为最优解。

所以若使第k(1≤k≤N-1)次变换后所得值最大,必使(k-1)次变换后所得值最大(符合贪心策略的特点2),在进行第k次变换时,只需取在进行(k-1)次变换后所得数列中的两最小数p,q施加f操作:p←p×q+1,q←∞即可(符合贪心策略特点1),因此此题可用贪心策略求解。在求min时,我们只需在每次变换的数列中找到两个最大数p,q施加作用 f:p←p×q+1,q←-∞即可.原理同上。

这是一道两次运用贪心策略解决的一道问题,它要求选手有较高的数学推理能力。

import java.util.Scanner;


public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int N = sc.nextInt();
		int [] n = new int[N];
		int max,min;
		for (int i = 0; i < N; i++) {
			n[i] = sc.nextInt();
		}
		int[] nclone = n.clone();//拷贝一次数组,因为有两次操作,分别求max和min。
		//求出MAX:
		int m = 0;
		while(m != N-1){
			for (int i = m; i < m+2; i++) {//循环为m到m+2,因为每次只要求出两个最小的值。
				for (int j = i+1; j < n.length; j++) {
					if(n[j]nclone[i]){//事实上只是将小于号改为大于号即可。
						int temp = nclone[j];
						nclone[j] = nclone[i];
						nclone[i] = temp;
					}
				}
				if(i==m+1){
					nclone[i] = nclone[i-1]*nclone[i]+1;
				}
			}
			m++;
		}
		min = nclone[N-1];
		
		//MAX - MIN :
		System.out.println(max - min);
	}
}


编程的思路:

每次排序仅排除最小(或最大)的两个数,然后将二者运算的结果放在第二个数的位置,然后从第二个数的位置开始往后排序,重复上述过程。最后得到数组最末尾的那个数就是运算的MAX(或MIN)的结果。MAX-MIN即可得解。

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