蓝桥杯练习一——合根植物Java代码bug

合根植物问题,自己写的代码,验证总有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);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值