目录
#牛客春招刷题训练营# + 【春招神助攻】牛客刷题营开启:每日一题攒牛币,大厂offer不是梦!_牛客网
#牛客春招刷题训练营# + 【春招神助攻】牛客刷题营开启:每日一题攒牛币,大厂offer不是梦!_牛客网
题目地址
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();
}
}