1. 程式人生 > 其它 >藍橋杯練習題 合根植物Java程式碼bug

藍橋杯練習題 合根植物Java程式碼bug

技術標籤:java後端資料結構演算法

合根植物問題,自己寫的程式碼,驗證總有bug,控制檯列印了以下陣列,發現了問題(第十行的315跨區域合根了),但是還是沒有找出來,程式碼bug究竟在哪裡,有沒有大神可幫助一下。
在這裡插入圖片描述

思路為:

  1. 接收輸入資料為兩個值node1 和 node2

  2. 判斷: 當node1為0且node2為0時,兩點無其他根,可合根,並將根的值賦為node1的座標。

place[node1] = node1;
place[node2] = node1;
3. 判斷: 當node2為0且node1不為0時,node1有根而node2無根,把node2的根連到node1上

place[node2] = place[node1];

4. 判斷: 當node1為0且node2不為0時,node2有根而node1無根,把node1的根連到node2上

place[node1] = place[node2];
5. 判斷: 當node1和node2都不為0時,node2和node1都有根,即為兩大部分合根(將所有node2的點連到node1上)。

因此遍歷整個陣列,如果發現某點和node2的值相等,證明其的根為node2,將這些點的值直接轉為node1.

以下為程式碼,仍有bug。謝謝大家幫忙


import java.util.HashSet;
import java.util.Scanner;

public class Main {
    public static int[] place;

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int m = input.nextInt();
        int n = input.nextInt();
        place = new int[m * n + 1];
        int number = input.nextInt();
        for (int i = 0; i < number; i++) {
            int node1 = input.nextInt();
            int node2 = input.nextInt();
            //node1 和 node2都不是和根
            if (place[node1] == 0 && place[node2] == 0) {
                place[node1] = node1;
                place[node2] = node1;
            } else if (place[node1] != 0 && place[node2] == 0) {
                place[node2] = place[node1];
            } else if (place[node1] == 0 && place[node2] != 0) {
                place[node1] = place[node2];
            } else if (place[node1] != 0 && place[node2] != 0) {
                if (place[node1] != place[node2]) {
                    for (int j = 1; j <= m * n; j++) {
                        if (place[j] == place[node2]) {
                            place[j] = place[node1];
                        }
                    }
                }
            }
        }
        HashSet<Integer> hashSet = new HashSet<>();
        int count = 0;
        for (int i = 1; i <= m * n; i++) {
            if (place[i] == 0)
                count++;
            else
                hashSet.add(place[i]);
        }
        System.out.println(hashSet.size() + count);
        for (int i = 1; i < m * n;i++) {
            System.out.printf("%4d" ,place[i]);
            if (i % 30 == 0)
                System.out.println();
        }
    }
}

已解決:

歷經三個小時debug, 哭遼哭遼。

問題在最後當兩個塊都不為0且不相同時,需遍歷整個陣列來將node2賦值給node1.

遍歷的目的為:將所有和arr[node2]相同的元素都改為node1。

然而在遍歷的for迴圈中,由於遍歷的過程中,當查到node2時,和其本身相同,因此會將node2所在元素也改為node1. 導致node2後所有的元素遍歷時變成了“將所有和arr[node1]相同的元素都改為node1”。從而使for迴圈遍歷改值無效。

因此,在遍歷前需自定義一個新變數,將arr[node2]的值提前賦給此變數,錯誤就會消除了。

以下為新程式碼,同時想到了另一個思路,不需要set去重。

每次合併的時候,除了兩個元素的數字一樣的情況外,其餘每次合併都一定會導致合根植物的數量-1, 因此引用count來作為計算少了的個數,提升速度。

package Hegenzhiwu;

import java.util.Scanner;

public class Main {
    public static int[] place;

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int m = input.nextInt();
        int n = input.nextInt();
        int count = 0;
        place = new int[m * n + 1];
        int number = input.nextInt();
        for (int i = 0; i < number; i++) {
            int node1 = input.nextInt();
            int node2 = input.nextInt();
            //node1 和 node2都不是和根
            if (place[node1] == 0 && place[node2] == 0) {
                place[node1] = node1;
                place[node2] = node1;
                count++;
            } else if (place[node1] != 0 && place[node2] == 0) {
                place[node2] = place[node1];
                count++;
            } else if (place[node1] == 0 && place[node2] != 0) {
                place[node1] = place[node2];
                count++;
            } else if (place[node1] != 0 && place[node2] != 0) {
                int value1 = place[node1];
                int value2 = place[node2];
                if (place[node1] != place[node2]) {
                    for (int j = 1; j <= m * n; j++) {
                        if (place[j] == value2) {
                            place[j] = value1;
                        }
                    }
                    count++;
                }
            }
        }
        System.out.println(m * n - count);
    }
}