2021寒假每日一题《整数集合划分》

整数集合划分

题目来源:PAT甲级真题1113
时间限制: 1000 m s 1000ms 1000ms 内存限制: 64 m b 64mb 64mb

题目描述

给定一个包含 N N N 个正整数的集合,请你将它划分为两个集合 A 1 A_1 A1 A 2 A_2 A2,其中 A 1 A_1 A1 包含 n 1 n_1 n1 个元素, A 2 A_2 A2 包含 n 2 n_2 n2 个元素。
集合中可以包含相同元素。
S 1 S_1 S1 表示集合 A 1 A_1 A1 内所有元素之和, S 2 S_2 S2 表示集合 A 2 A_2 A2 内所有元素之和。
请你妥善划分,使得 ∣ n 1 − n 2 ∣ |n_1−n_2| n1n2 尽可能小,并在此基础上 ∣ S 1 − S 2 ∣ |S_1−S_2| S1S2 尽可能大。

输入格式

第一行包含整数 N N N
第二行包含 N N N 个正整数。

输出格式

在一行中输出 ∣ n 1 − n 2 ∣ |n_1−n_2| n1n2 ∣ S 1 − S 2 ∣ |S_1−S_2| S1S2 ,两数之间空格隔开。

数据范围

2 ≤ N ≤ 1 0 5 2 ≤ N ≤ 10^5 2N105 ,
保证集合中各元素以及所有元素之和小于 2 31 2^{31} 231

样例输入1

10
23 8 10 99 46 2333 46 1 666 555

样例输出1

0 3611

样例输入2

13
110 79 218 69 3721 100 29 135 2 6 13 5188 85

样例输出2

1 9359

解题思路:贪心

题目让两个集合的元素 个数之差最小数值总和之差最大 ,所以尽量均分个数。
元素个数为偶数的时候,分开后,两个集合元素个数一样,差值为 0 0 0
元素个数为奇数的时候,分开后,元素个数差值为 1 1 1
然后要求子集合差值尽量大,那么一个集合里放小的元素,一个集合里放大的元素就行了。
N N N 为奇数的时候,不能均分,就在大元素的集合里,多放一个元素。
具体划分两个集合的思路如下:

  • 将数组排序后,将 [ 0 , n / 2 ) [0,n/2) [0,n/2) , [ n / 2 , n ] [n/2,n] [n/2,n] 分别作为 A 1 A_1 A1 , A 2 A_2 A2 两个集合。
  • 数值总和之差 = 所有元素总和 - 两倍的 [ 0 , n / 2 ) [0,n/2) [0,n/2) 区间的总和。

读入给定的数组,边读入边计算所有元素的总和。
然后减去两倍的 [ 0 , n / 2 ) [0,n/2) [0,n/2) 区间的总和,即得到最大的数值总和之差。
个数之差根据输入的 N N N 来判断,N为偶数则个数之差最小为0,否则为1。

解题代码-Java

import java.util.*;

public class Main {
     
    public static void main(String[] args) {
     
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();
        int[] a = new int[n];
        long s = 0;
        for (int i = 0; i < n; i++) {
     
            a[i] = input.nextInt();
            s += a[i];
        }
        input.close();

        Arrays.sort(a);

        for (int i = 0; i < n / 2; i++) {
     
            s -= 2L * a[i];
        }

        System.out.printf("%d %d\n", n % 2, s);
    }
}

你可能感兴趣的:(2021寒假每日一题,java,算法,贪心算法)