数组先小于等于再大于等于的调整

给定数组 arr,请将数组调整成 a <= b >= c <= d >= e <= f...的样子

例如,arr = {3,1,2}
调整之后,arr 可以是{1,3,2}. 1 <= 3 >=2
调整之后,arr 也可以是{2,3,1}. 2 <= 3 >=1
arr = {3,1,2,6}
调整之后,arr 可以是{1,6,2,3}. 1 <= 6 >= 2 <= 3
调整之后,arr 也可以是{3,6,1,2}. 3 <= 6 >= 1 <= 2

1,如果 arr 长度为 N,要求时间复杂度为 O(N),额外空间复杂度为 O(1)。
2,arr 可能会不止一种调整方案,但只要满足要求即可。


算法原形:完美洗牌算法


public static void shuffle(int[] arr, int l, int r){
	while(r - l + 1 > 0){
		int lenAndOne = r - l + 2;
		int bloom = 3;
		int k = 1;
		while(bloom <= lenAndOne / 3){
			bloom += 3;
			k++;
		}
		int m = (bloom - 1) / 2;
		int mid = (l + r) / 2;
		rotate(arr, l + m, mid, mid+m);
		cycles(arr, l - 1, bloom, k);
		l = l + bloom - 1;
	}
}

public static void cycles(int[] arr, int base, int bloom, int k){
	for(int i = 0, trigger = 1; i < k; i++, trigger += 3){
		int next = (2*trigger) % bloom;
		int cur = next;
		int record = arr[next + base];
		int tmp = 0;
		arr[next + base] = arr[trigger + base];
		while(cur != trigger){
			next = (2 * cur) %bloom;
			tmp = arr[next + base];
			arr[next + base] = record;
			cur = next;
			record = tmp;
		}
	}
}

public static void rotate(int[] arr, int l, int m, int r){
	reverse(arr, l, m);
	reverse(arr, m + 1, r);
	reverse(arr, l ,r);
}

public static void reverse(int[] arr, int l, int r){
	while(l < r){
		int tmp = arr[l];
		arr[l++] = arr[r];
		arr[r--] = tmp;
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的实现: 1. 创建一个数组,其中每个元素表示一个奖品的中奖概率。 2. 计算所有奖品的中奖概率总和。 3. 如果总和小于等于100%,则直接返回该数组作为中奖概率。 4. 如果总和大于100%,则需要对数组中的元素进行调整,使得总和小于等于100%。 5. 对于每个超出100%的元素,将其值减去超出部分的比例,然后将这个比例分配给其他元素,直到总和小于等于100%为止。 以下是Java代码实现: ```java public static double[] adjustProbabilities(double[] probabilities) { double sum = 0; for (double p : probabilities) { sum += p; } if (sum <= 1.0) { return probabilities; } double[] adjusted = Arrays.copyOf(probabilities, probabilities.length); while (sum > 1.0) { double excess = sum - 1.0; int maxIndex = 0; double maxVal = adjusted[0]; for (int i = 1; i < adjusted.length; i++) { if (adjusted[i] > maxVal) { maxIndex = i; maxVal = adjusted[i]; } } double adjustment = Math.min(excess, maxVal - 1.0); adjusted[maxIndex] -= adjustment; excess -= adjustment; for (int i = 0; i < adjusted.length; i++) { if (i != maxIndex && excess > 0) { double transfer = Math.min(excess, 1.0 - adjusted[i]); adjusted[i] += transfer; excess -= transfer; } } sum = 0; for (double p : adjusted) { sum += p; } } return adjusted; } ``` 该方法接受一个double类型的数组,表示每个奖品的中奖概率,返回一个调整后的数组,使得所有奖品的中奖概率总和小于等于1.0。注意,该方法并没有对输入数组进行修改,而是返回一个新的数组,因此需要在调用该方法后使用返回值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值