疯狂队列问题

小易老师是非常严厉的,它会要求所有学生在进入教室前都排成一列,并且他要求学生按照身高不递减的顺序排列。有一次,n个学生在列队的时候,小易老师正好去卫生间了。学生们终于有机会反击了,于是学生们决定来一次疯狂的队列,他们定义一个队列的疯狂值为每对相邻排列学生身高差的绝对值总和。由于按照身高顺序排列的队列的疯狂值是最小的,他们当然决定按照疯狂值最大的顺序来进行列队。现在给出n个学生的身高,请计算出这些学生列队的最大可能的疯狂值。小易老师回来一定会气得半死。

输入描述:
输入包括两行,第一行一个整数n(1 ≤ n ≤ 50),表示学生的人数
第二行为n个整数h[i](1 ≤ h[i] ≤ 1000),表示每个学生的身高


输出描述:
输出一个整数,表示n个学生列队可以获得的最大的疯狂值。

如样例所示: 
当队列排列顺序是: 25-10-40-5-25, 身高差绝对值的总和为15+30+35+20=100。
这是最大的疯狂值了。
示例1

输入

5
5 10 25 40 25

输出

100

解法:

import java.util.Arrays;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int[] nums = new int[n];
		for(int i = 0; i < n; i++){
			nums[i] = in.nextInt();
		}
		
		int[] resort = new int[n];
		Arrays.sort(nums);
		int center = n % 2 == 0 ? n / 2 : n / 2 + 1;//center代表的是中点是第几个数,不是下标,下标要减1
		resort[center - 1] = nums[n - 1];
		int leftMove = center - 1 - 1;
		int rightMove = center - 1 + 1;

		//大的数和小的数交叉进行穿插,每次插两个小的,再插两个大的,所以需要一个变量来判断该插什么了
		//以leftMove和rightMove作为循环控制条件
		int sob = 0;//0代表插小的,1代表插大的
		int small = 0;
		int big = n - 1 - 1;
		
		while(leftMove >= 0 && rightMove <= n - 1){
			//System.out.println("df");
			if(sob == 0){
				resort[leftMove--] = nums[small++];
				resort[rightMove++] = nums[small++];
				sob = 1;
			}else{
				resort[leftMove--] = nums[big--];
				resort[rightMove++] = nums[big--];
				sob = 0;
			}
		}
		
		if(leftMove < 0 && rightMove > n - 1){
			//System.out.println("...");
			//说明刚好完成,不用管
		} else if(leftMove < 0){
			if(sob == 0){
				resort[n - 1] = nums[small++];
				sob = 1;
			}else{
				resort[n - 1] = nums[big--];
				sob = 0;
			}
		} else{
			if(sob == 0){
				resort[0] = nums[small++];
				sob = 1;
			}else{
				resort[0] = nums[big--];
				sob = 0;
			}
		}
		
		//最后要调整,因为要差值最大,所以较小的数尽量不要放在首尾(也只是针对n偶数的情况)
		//[11 5 17 2 19 3 13 7]与[5, 17, 2, 19, 3, 13, 7, 11],是否顺移一位
		if(Math.abs(resort[n - 1] - resort[n - 2]) < Math.abs(resort[n - 1] - resort[0])){
			int temp = resort[n - 1];
			for(int i = n - 1; i >= 1; i--){
				resort[i] = resort[i - 1];
			}
			resort[0] = temp;
		}
		//System.out.println(Arrays.toString(resort));
		int sum = 0;
		for(int i = 0; i < n - 1; i++){
			sum += Math.abs(resort[i + 1] - resort[i]);
		}
		System.out.println(sum);
		in.close();
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值