合根植物问题,自己写的代码,验证总有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];
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);
}
}