簡體   English   中英

為什么我的聯合查找不交集集算法不能通過所有測試用例?

[英]Why is my Union Find Disjoint Sets algo for this problem not passing all test cases?

輸入樣例:

1
3 2
1 2
2 3

第一行=測試用例數

第二行的第一人數=人數

第二行的第二個數字=友誼數F

遵循F線=友誼

輸出將是最大的朋友組的大小。

因此,該輸入的樣本輸出為3。[[1、2、3])

我的解決方案:

import java.util.Scanner;
import java.util.HashMap;
import java.util.Collections;

public class Main {

    public static void main (String args[]) {
        Scanner reader = new Scanner(System.in);
        int tests = reader.nextInt();
        for (int i = 0; i < tests; i++) {
            int numcitizens = reader.nextInt();
            // the input is 1-indexed so I create the parent array as such
            int[] parent = new int[numcitizens + 1];
            for (int j = 0; j < (numcitizens + 1); j++) {
                parent[j] = j;
            }
            int[] rank = new int[numcitizens + 1];
            int numpairs = reader.nextInt();
            for (int j = 0; j < numpairs; j++) {
                int A = reader.nextInt();
                int B = reader.nextInt();
                union(A, B, parent, rank);
            }
            HashMap<Integer, Integer> histo = new HashMap<Integer, Integer>();
            for (int j = 1; j < parent.length; j++) {
                int root = parent[j];
                if (!histo.containsKey(root)) {
                    histo.put(root, 1);
                }
                else {
                    histo.put(root, histo.get(root) + 1);
                }

            }
            int max = Collections.max(histo.values());
            System.out.println(max);
        }
    }

    // UFDS find
    static int find(int x, int[] parent) {

        if (parent[x]!= x) {
            parent[x] = find(parent[x], parent);
        }

        return parent[x];
    }

    // UFDS union
    static void union(int x, int y, int[] parent, int[] rank) {
        int xRoot = find(x, parent);
        int yRoot = find(y, parent);

        if (xRoot == yRoot) {
            return;
        }
        else {
            if (rank[xRoot] < rank[yRoot]) {
                parent[xRoot] = yRoot;
            }

            else if (rank[yRoot] < rank[xRoot]) {
                parent[yRoot] = xRoot;
            }

            else {
                parent[yRoot] = xRoot;
                for (int i = 0; i < parent.length; i++) {
                    if (parent[i] == yRoot) {
                        parent[i] = xRoot;
                    }
                }
                rank[xRoot] = rank[xRoot] + 1;
            }
        }
    }
}

它適用於示例輸入,但是當通過在線判斷系統(通過數百個測試用例運行它)時,它會告訴我錯誤的輸出。 不知道我的錯誤可能在哪里? 在我看來,這是一個簡單的UFDS問題。

您放入union的for循環會破壞性能。 拿出來

在直方圖循環中,您需要int root = find(j,parent);

numcitizens為零時,您的代碼將引發異常。

修復這些問題,您的代碼將正常運行。

這里有一些額外的提示:

  • 我總是按大小合並而不是按等級合並。 它具有相同的復雜性,並且大小通常很有用。 在這種情況下,您將不需要構建直方圖,因為您將擁有每個根的大小。

  • 我使用單個int[]數組作為數據結構。 如果值v > = 0,則它是具有該大小的根集(0表示該索引處沒有集或空集)。 否則, 〜v是到父集的鏈接。 我最近在此答案中使用了該結構: 算法:使用聯合查找來計算島的數量

每個人擁有的朋友數量不是parent數組。每個人的排名是由集合表示的樹的高度,即該人擁有的朋友數量。 因此請在for循環中使用root=rank[j]+1來計算最大朋友數。

int max=Integer.MAX_VALUE;
for(int r:rank){
    max=Math.max(max,r+1);
}
System.out.println(max);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM