最小极差分组
华为OD机试新系统真题 华为OD上机考试新系统真题 6月28号 100分题型
华为OD机试新系统真题目录点击查看: 华为OD机试新系统真题题库目录|机考题库 + 算法考点详解
题目内容
给定
n
n
n 个整数,你需要将它们任意分成两组,且两组都不能为空。
对于一组数,它的极差定义为该组中的最大值减去最小值。
设两组分别为第
1
1
1 组和第
2
2
2 组,则它们的极差分别为:
- 第 1 1 1 组极差 = = = 第 1 1 1 组最大值 − - − 第 1 1 1 组最小值
- 第
2
2
2 组极差
=
=
= 第
2
2
2 组最大值
−
-
− 第
2
2
2 组最小值
你的目标是最小化这两个极差之和,即最小化:
( max 1 − min 1 ) + ( max 2 − min 2 ) (\text{max}1-\text{min}1)+(\text{max}2-\text{min}2) (max1−min1)+(max2−min2)
请输出这个最小值。
样例1
输入
5
10 1 5 3 8
输出
6
说明
划分为
[
10
,
8
]
[10,8]
[10,8] 和
[
1
,
5
,
3
]
[1,5,3]
[1,5,3] 两组
- 左极差 = = = 5 5 5- 1 1 1 = = = 4 4 4
- 右极差 = = = 10 10 10- 8 8 8 = = = 2 2 2
- 总和 = = = 6 6 6
样例2
输入
5
1 1 9 1 9
输出
0
说明
分组为
[
1
,
1
,
1
]
[1,1,1]
[1,1,1] 和
[
9
,
9
]
[9,9]
[9,9]
两组的极差均为
0
0
0,和也为
0
0
0
样例3
输入
2
1 2
输出
0
说明
只能分为两组,每组一个数。每组的最大最小值是同一个数,极差为
0
0
0。
题解
思路:逻辑分析
- 先对输入数组
nums进行升序排序。 - 接下来考虑两种情况
- 最大值和最小值位于同一组
nums[0], nums[n-1], 要想整体和最小,另一组的max - min最小为0,只包含一个数,此时能够取得的极差为nums[n-1] - nums[0] - 最大值和最小值位于不同组中,此时可以通过枚举切分点为i,其中
nums[i]和nums[0]位于同一组,贡献极差为nums[i] - nums[0], 另一组能够贡献的极差达到最小,则需要[0....i]同属一组,这种切分极差为nums[i] - nums[0] + nums[n-1] - nums[i+1]
- 最大值和最小值位于同一组
- 按照2逻辑进行枚举,记录其中最小值就是结果。
c++
#include<bits/stdc++.h>
#include <vector>
using namespace std;
long minGroupValue(int n, vector<int>& nums) {
// 升序排序
sort(nums.begin(), nums.end());
if (n == 2) {
return 0;
}
// 最小值和最大值为同一组,能够得到的最小极差
long ans = nums[n - 1] - nums[0];
// 最小值和最大值不属于同一组情况,枚举分割点
for (int i = 0; i < n - 1; i++) {
long cost = nums[i] - nums[0] + nums[n-1] - nums[i + 1];
if (cost < ans) {
ans = cost;
}
}
return ans;
}
int main() {
int n;
cin >> n;
vector<int> nums(n);
for (int i = 0; i < n; i++) {
cin >> nums[i];
}
cout << minGroupValue(n, nums);
return 0;
}
Java
import java.util.*;
public class Main {
public static long minGroupValue(int n, int[] nums) {
// 升序排序
Arrays.sort(nums);
if (n == 2) {
return 0;
}
// 最小值和最大值为同一组,能够得到的最小极差
long ans = (long) nums[n - 1] - nums[0];
// 最小值和最大值不属于同一组情况,枚举分割点
for (int i = 0; i < n - 1; i++) {
long cost = (long) nums[i] - nums[0] + (long) nums[n - 1] - nums[i + 1];
if (cost < ans) {
ans = cost;
}
}
return ans;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] nums = new int[n];
for (int i = 0; i < n; i++) {
nums[i] = scanner.nextInt();
}
System.out.println(minGroupValue(n, nums));
}
}
Python
def minGroupValue(n, nums):
# 升序排序
nums.sort()
if n == 2:
return 0
# 最小值和最大值为同一组,能够得到的最小极差
ans = nums[-1] - nums[0]
# 最小值和最大值不属于同一组情况,枚举分割点
for i in range(n - 1):
cost = nums[i] - nums[0] + nums[-1] - nums[i + 1]
if cost < ans:
ans = cost
return ans
n = int(input())
nums = list(map(int, input().split()))
print(minGroupValue(n, nums))
JavaScript
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const input = [];
rl.on("line", (line) => {
input.push(line);
});
rl.on("close", () => {
let index = 0;
const n = parseInt(input[index++]);
const nums = input[index++].split(" ").map(Number);
console.log(minGroupValue(n, nums).toString());
});
function minGroupValue(n, nums) {
// 升序排序
nums.sort((a, b) => a - b);
if (n === 2) {
return 0;
}
// 最小值和最大值为同一组,能够得到的最小极差
let ans = nums[n - 1] - nums[0];
// 最小值和最大值不属于同一组情况,枚举分割点
for (let i = 0; i < n - 1; i++) {
const cost = nums[i] - nums[0] + nums[n - 1] - nums[i + 1];
if (cost < ans) {
ans = cost;
}
}
return ans;
}
Go
package main
import (
"fmt"
"sort"
)
func minGroupValue(n int, nums []int) int64 {
// 升序排序
sort.Ints(nums)
if n == 2 {
return 0
}
// 最小值和最大值为同一组,能够得到的最小极差
ans := int64(nums[n-1] - nums[0])
// 最小值和最大值不属于同一组情况,枚举分割点
for i := 0; i < n-1; i++ {
cost := int64(nums[i]-nums[0] + nums[n-1] - nums[i+1])
if cost < ans {
ans = cost
}
}
return ans
}
func main() {
var n int
fmt.Scan(&n)
nums := make([]int, n)
for i := 0; i < n; i++ {
fmt.Scan(&nums[i])
}
fmt.Println(minGroupValue(n, nums))
}
C语言
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a, const void *b) {
return (*(int *)a) - (*(int *)b);
}
long minGroupValue(int n, int nums[]) {
// 升序排序
qsort(nums, n, sizeof(int), cmp);
if (n == 2) {
return 0;
}
// 最小值和最大值为同一组,能够得到的最小极差
long ans = (long)nums[n - 1] - nums[0];
// 最小值和最大值不属于同一组情况,枚举分割点
for (int i = 0; i < n - 1; i++) {
long cost = (long)nums[i] - nums[0] + (long)nums[n - 1] - nums[i + 1];
if (cost < ans) {
ans = cost;
}
}
return ans;
}
int main() {
int n;
scanf("%d", &n);
int nums[n];
for (int i = 0; i < n; i++) {
scanf("%d", &nums[i]);
}
printf("%ld\n", minGroupValue(n, nums));
return 0;
}

45万+

被折叠的 条评论
为什么被折叠?



