# 149. 好数组

贪心思路:

整体思路是移动到中间位置(中位数),一定是 移动次数最小的。

有一个数可以不改变,对数组排序之后, 最小数 和 最大数 一定是移动次数最多的,所以分别保留最小 和 最大的不变。

中间可能有两个位置,所以要计算中间偏前 和 中间偏后的

代码如下:

#include<bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<long> arr(n);
    for (int i = 0; i < n; ++i) {
        cin >> arr[i];
    }
    sort(arr.begin(), arr.end());

    if (arr[0] == arr[n - 1]) {
        cout << 1 << endl;
        return 0;
    }
    long cnt = 0L;
    long cnt1 = 0L;

    // 如果要保留一个不改变,要不不改最小的,要不不改最大的。

    // 取中间偏前的位置
    long mid = arr[(n - 2) / 2];

    // 不改最大的
    for (int i = 0; i < n - 1; i++) {
        cnt += abs(arr[i] - mid);
    }

    // 取中间偏后的位置
    mid = arr[n / 2];

    // 不改最小的
    for (int i = 1; i < n; i++) {
        cnt1 += abs(arr[i] - mid);
    }

    cout << min(cnt, cnt1) << endl;
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

Java代码如下:


import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        long[] arr = new long[n];
        for (int i = 0; i < n; ++i) {
            arr[i] = scanner.nextLong();
        }
        Arrays.sort(arr);

        if (arr[0] == arr[n - 1]) {
            System.out.println(1);
            return;
        }
        long cnt = 0L;
        long cnt1 = 0L;

        // 如果要保留一个不改变,要不不改最小的,要不不改最大的。

        // 取中间偏前的位置
        long mid = arr[(n - 2) / 2];

        // 不改最大的
        for (int i = 0; i < n - 1; i++) {
            cnt += Math.abs(arr[i] - mid);
        }

        // 取中间偏后的位置
        mid = arr[n / 2];

        // 不改最小的
        for (int i = 1; i < n; i++) {
            cnt1 += Math.abs(arr[i] - mid);
        }

        System.out.println(Math.min(cnt, cnt1));
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
上次更新:: 3/4/2025, 5:49:45 PM
@2021-2025 代码随想录 版权所有 粤ICP备19156078号