[Leetcode] 765. Couples Holding Hands (with mathematical proof)

Posted by sunnypal on Tue, 04 Jan 2022 09:35:40 +0100

Title address:

https://leetcode.com/problems/couples-holding-hands/

There is a given length 2 n 2n 2n array A A A. Number by 0 ∼ 2 n − 1 0\sim 2n-1 It is composed of 0 ∼ 2n − 1. It is required to exchange several times so that for any k k k, 2 k 2k 2k and 2 k + 1 2k+1 2k+1 two numbers are adjacent. Returns the minimum number of swaps.

First, if you want to end each 2 k 2k 2k and 2 k + 1 2k+1 2k+1 are next to each other, so each number pair must occupy the shape 2 a , 2 a + 1 2a,2a+1 2a, the subscript of 2A + 1, otherwise it will cause A [ 0 ] A[0] If A[0] is in a single position, it is contradictory. Next we will A [ 0 : 1 ] , A [ 2 : 3 ] , . . . A[0:1],A[2:3],... A[0:1],A[2:3],... These two positions are regarded as a whole, as the vertices of the graph, and then 2 k 2k 2k and 2 k + 1 2k+1 Edges are connected between the vertices where 2k+1 is located (if they are already in the same vertex, they don't need to be connected).

Consider any connected block. If the connected block contains only one vertex, they have been matched and need not be ignored. If contain m m m vertices, we prove that if only considered in this subgraph, at least m − 1 m-1 m − 1 exchange. first m − 1 m-1 The scheme of m − 1 exchange exists, and the second exchange can be carried out first 1 1 Adjust the first vertex, and then adjust the second vertex in turn 2 , 3 , . . . , m − 1 2,3,...,m-1 2,3,...,m − 1 vertex, passing through the least m − 1 m-1 After m − 1 adjustment, the second m m m vertices must have automatically met the conditions; Secondly, we prove that there is no exchange scheme with less times, which can be proved by mathematical induction m = 1 m=1 In the case of m=1, it is obvious that for m − 1 m-1 The case of m − 1 point is also correct, so if m m m points have less than or equal to m − 2 m-2 For the scheme of m − 2 exchange, one step must be to adjust the second exchange m m m points, let's advance this step to the third 1 1 Step 1, then there will be less than or equal to m − 3 m-3 Scheme adjustment of m − 3 m − 1 m-1 m − 1 point, which contradicts the inductive hypothesis.

Next, since the whole graph is composed of several connected blocks, the total minimum number of exchanges is ∑ i ( m i − 1 ) \sum_i (m_i-1) ∑i​(mi​−1), m i m_i mi , yes i i i number of connected blocks. We only need to prove that the minimum exchange scheme must not include the step of exchanging the numbers in different connected blocks. If it does, then the two connected blocks will be connected into a connected block, and the minimum number of steps will be more than the addition of the minimum number of steps in the two connected blocks 1 1 1. It's contradictory. Therefore, the optimal scheme is the internal adjustment of the same connected block.

The code is as follows:

import java.util.HashMap;
import java.util.Map;

public class Solution {
    
    // Open a union search set with statistical set size
    class UnionFind {
        private int[] p;
        int[] sz;
        
        public UnionFind(int size) {
            p = new int[size];
            sz = new int[size];
            for (int i = 0; i < size; i++) {
                p[i] = i;
                sz[i] = 1;
            }
        }
        
        public int find(int x) {
            if (p[x] != x) {
                p[x] = find(p[x]);
            }
            
            return p[x];
        }
        
        public void union(int x, int y) {
            int px = find(x), py = find(y);
            if (px != py) {
                p[px] = py;
                sz[py] += sz[px];
            }
        }
    }
    
    public int minSwapsCouples(int[] row) {
        UnionFind uf = new UnionFind(row.length / 2);
        Map<Integer, Integer> map = new HashMap<>();
        // Combine the subscript union of the number pair where 2k and 2k + 1 are located
        for (int i = 0; i < row.length; i++) {
            if (map.containsKey(row[i] ^ 1)) {
                int id = map.get(row[i] ^ 1) / 2;
                uf.union(id, i / 2);
            }
            
            map.put(row[i], i);
        }
    
        int res = 0;
        for (int i = 0; i < row.length / 2; i++) {
            if (uf.find(i) == i) {
                res += uf.sz[i] - 1;
            }
        }
        
        return res;
    }
}

Time complexity O ( n log ⁡ ∗ n ) O(n\log^*n) O(nlog * n), space O ( n ) O(n) O(n).

Topics: Java Algorithm data structure