牛客春招刷题训练营 算法 Java 3月28日 不要三句号的歪 尼科彻斯定理 隐匿社交网络

#牛客春招刷题训练营# + https://www.nowcoder.com/discuss/726480854079250432

题目地址

https://www.nowcoder.com/practice/7cbb7d96fb354f7995d9af1ccf8906b4?channelPut=w25springcamp

https://www.nowcoder.com/practice/dbace3a5b3c4480e86ee3277f3fe1e85?channelPut=w25springcamp

https://www.nowcoder.com/practice/2870f9db6aeb4eb08fbd6460397f9bf4?channelPut=w25springcamp

1.不要三句号的歪

这是我们写的第一个方法

先用指针寻址

然后往回找

import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String str=in.next();
        str=str.replace("."," ");
        str=str.replace(" ","");
        // System.out.println(str);
        int qian=-1;
        int hou=-1;
        for(int i=0;i<str.length()-1;i++){
            if(str.charAt(i)==','&&str.charAt(i+1)==','){
                qian=i-1;
                hou=i+2;
                break;
            }
        }
        // System.out.println(qian+" "+hou);
        StringBuilder sb1=new StringBuilder();
        sb1.append(str.charAt(qian));
        qian--;
        while(qian>0&&str.charAt(qian)!=','){
            sb1.append(str.charAt(qian));
            qian--;
        }
        String str1=sb1.reverse().toString();
        // System.out.println(str1);

        StringBuilder sb2=new StringBuilder();
        sb2.append(str.charAt(hou));
        hou++;
        while(hou<str.length()&&str.charAt(hou)!=','){
            sb2.append(str.charAt(hou));
            hou++;
        }
        String str2=sb2.toString();
        // System.out.println(str2);
        System.out.print(Long.parseLong(str2)-Long.parseLong(str1)-1);
    }
}

这是我看答案的写法

顿悟

我们做三次切割即可 具体逻辑就两次

第一次切割 我们将字符串切割成左右两部分 切割字符串 ",...,"

第二次切割 我们将左边的字符串按 "," 切割

第三次切割 我们将右边的字符串按 "," 切割

然后 后面那个数组的第一部分 减去前面数组的最后一部分

最后将答案减去 1 就行

import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String str=in.next();
        String[] arr=str.split(",...,");
        String[] arr1=arr[0].split(",");
        String[] arr2=arr[1].split(",");
        System.out.println(Long.parseLong(arr2[0])-Long.parseLong(arr1[arr1.length-1])-1);
    }
}

2.尼科彻斯定理

依旧是找规律

我们发现中间那个数等于 n*n

然后再推出两边的元素

import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int n=in.nextInt();
         long middle = n*n;
            long k=middle-n+1;
            for(int i=0;i<n;i++){
                System.out.print(k);
                if(i!=n-1){
                    System.out.print("+");
                }
                k+=2;
            }
    }
}

3.隐匿社交网络

很显然这题的处理查找问题上 子集元素最多问题 我们可以使用并查集

然后就是什么时候合并

按位与操作运算得到的结果是 0 的两个数不能合并

两个二进制的表示在每一位上不能同时为 1 的两个数按位与运算是 0

所以我们找到了每一位的数

只要是有某一位上的数都是 1 就进行合并

合并后 看一下最大的子集的元素个数 就得出了我们需要的答案

import java.util.Scanner;

public class Main {
    // 定义常量 N
    static final int N = 100006;
    // 二维数组 ejz 用于存储每个数的二进制形式
    static int[][] ejz = new int[N][1000];
    // 数组 arr 用于存储输入的数
    static long[] arr = new long[N];
    // p 数组用于维护集合,si 数组用于维护集合中的个数
    static int[] p = new int[N];
    static int[] si = new int[N];

    // 查找元素所在集合的根节点
    static int find(int a) {
        if (p[a] != a) {
            p[a] = find(p[a]);
        }
        return p[a];
    }

    // 合并两个元素所在的集合
    static void merge(int a, int b) {
        int pa = find(a);
        int pb = find(b);
        if (pa != pb) {
            p[pa] = pb;
            si[pb] += si[pa];
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int T = scanner.nextInt();
        while (T-- > 0) {
            int n = scanner.nextInt();
            int ma_idx = 0;

            for (int i = 0; i < n; i++) {
                for (int j = 0; j < 1000; j++) {
                    ejz[i][j] = 0;
                }
            }

            for (int i = 0; i < n; i++) {
                arr[i] = scanner.nextLong();
                long x = arr[i];
                int idx = 0;
                while (x > 0) {
                    ejz[i][idx] = (int) (x % 2);
                    idx++;
                    x /= 2;
                }
                ma_idx = Math.max(ma_idx,  idx);
            }

            for (int i = 0; i < n; i++) {
                p[i] = i;
                si[i] = 1;
            }

            for (int i = 0; i < ma_idx; i++) {
                int j = 0;
                while (j < n && ejz[j][i] == 0) {
                    j++;
                }
                for (int k = j + 1; k < n; k++) {
                    if (ejz[k][i] == 1) {
                        merge(k, j);
                    }
                }
            }

            // 找出最大的集合大小
            int ans = 1;
            for (int i = 0; i < n; i++) {
                ans = Math.max(ans,  si[i]);
            }

            // 输出结果
            System.out.println(ans);
        }
        scanner.close();
    }
}

#牛客春招刷题训练营#
牛客算法 校招 Java 合集 文章被收录于专栏

Java写算法

全部评论

相关推荐

03-27 08:29
安徽大学 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务