藍橋杯練習題 合根植物Java程式碼bug
合根植物問題,自己寫的程式碼,驗證總有bug,控制檯列印了以下陣列,發現了問題(第十行的315跨區域合根了),但是還是沒有找出來,程式碼bug究竟在哪裡,有沒有大神可幫助一下。
思路為:
-
接收輸入資料為兩個值node1 和 node2
-
判斷: 當node1為0且node2為0時,兩點無其他根,可合根,並將根的值賦為node1的座標。
place[node1] = node1;
place[node2] = node1;
3. 判斷: 當node2為0且node1不為0時,node1有根而node2無根,把node2的根連到node1上
place[node2] = place[node1];
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去重。
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);
}
}