Key idea: Counting sort. Time should be O(N).
Algorithm: Time = O(N).
- Counting each value 1, 2, 3, i.e., Count[1], Count[2], Count[3].
 - Count[1] + Count[2] + Count[3] = N
 - Target intervals:
 - I_1 = [0, Count[1])
 - I_2 = [Count[1], Count[1] + Count[2])
 - I_3 = [Count[1] + Count[2], Count[1] + Count[2] + Count[3])
 - Counting each value on 3 different target intervals.
 - Define Count[i][j] = # of value i in the interval I_j.
 - Swap i and j in min(Count[i][j], Count[j][i]) times for i ≠ j.
 - Swap the rest unsorted values.
 - Let T_ij = abs(Count[i][j] - Count[j][i]).
 - Property: T_ij = T_jk = T_ki.
 - Let T = T_ij = T_jk = T_jk.
 - Swap 1 -> 2 -> 3 cyclically: Take 2T times.
 
#include <iostream>
#include <fstream>
using namespace std;
int main() {
    ofstream fout("sort3.out");
    ifstream fin("sort3.in");
    int N;
    fin >> N;
    int values[1000] = {0};
    int value_counts[3] = {0};
    int swapping_map[3][3] = {0};
    for (int i = 0; i < N; i++) {
        fin >> values[i];
        value_counts[values[i] - 1]++;
    }
    int begin_pos = 0;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < value_counts[i]; j++) {
            swapping_map[i][values[begin_pos + j] - 1]++;
        }
        begin_pos += value_counts[i];
    }
    int swapping_count = 0;
    swapping_count += min(swapping_map[0][1], swapping_map[1][0]); // 1 <-> 2
    swapping_count += min(swapping_map[1][2], swapping_map[2][1]); // 2 <-> 3
    swapping_count += min(swapping_map[2][0], swapping_map[0][2]); // 3 <-> 1
    swapping_count += 2 * abs(swapping_map[0][1] - swapping_map[1][0]); // 1 -> 2 -> 3
    fout << swapping_count << '\n';
    return 0;
}
沒有留言:
張貼留言