2024/8/18 字节跳动25秋招第一场笔试 后端 算法
时间是2024/8/18 晚上7点到9点 两个半小时
总共4道算法题
第一题
定义一个数组为特殊数组:数组大小至少为3 只有两种数字组成 且其中一种数字恰好出现一次
例如[1,1,4][1,4,1]是特殊数组
例如[1,4][5,1,4][1,1,1]不是特殊数组
给出一个长度为n的数组 问有多少个子数组是特殊数组
当时想用滑动窗口解 超时 只过了20%
package Dduo;
import java.math.BigInteger;
import java.util.*;
public class Main {
static Scanner sc = new Scanner(System.in);
static long mod = (long) (1e9 + 7);
static int cnt = 0;
public static void main(String[] args) {
int t = 1;
// t=sc.nextInt();
while (t-- > 0) {
solve();
}
sc.close();
return;
}
private static void solve() {
int n=sc.nextInt();
int arr[]=new int[n];
for(int i=0;i<n;i++)arr[i]=sc.nextInt();
System.out.print(count(arr));
}
public static int count(int[] a) {
int n = a.length;
int specialCount = 0;
for (int start = 0; start < n; start++) {
Map<Integer, Integer> freq = new HashMap<>();
for (int end = start; end < n; end++) {
int num = a[end];
freq.put(num, freq.getOrDefault(num, 0) + 1);
if (freq.size() == 2) {
int[] counts = new int[2];
int index = 0;
for (int count : freq.values()) {
counts[index++] = count;
}
if (counts[0] == 1 || counts[1] == 1) {
if (end - start + 1 >= 3) {
specialCount++;
}
}
}
}
}
return specialCount;
}
}
第二题
现在有n个事件
每个事件可以在两种选项中选择一种
1 消耗x颗宝石 获得y金币
2 获得z宝石
不过宝石不能大于m 大于m的部分会消失
在n个事件结束后 每拥有一颗宝石 都可以换算成1个金币
一开始没有宝石 想知道在最优策略下 可以获得多少金币
线性解的 过了15%
想想应该用动态规划吧
package Dduo;
import java.math.BigInteger;
import java.util.*;
public class Main {
static Scanner sc = new Scanner(System.in);
static long mod = (long) (1e9 + 7);
static int cnt = 0;
public static void main(String[] args) {
int t = 1;
// t=sc.nextInt();
while (t-- > 0) {
solve();
}
sc.close();
return;
}
private static void solve() {
int n=sc.nextInt();//n行
int m=sc.nextInt();//上限
int arr[][]=new int[n][3];
for(int i=0;i<n;i++) {
arr[i][0]=sc.nextInt();//消耗宝石
arr[i][1]=sc.nextInt();//获取金币
arr[i][2]=sc.nextInt();//直接获取宝石
}
int cntBS=arr[0][2];
int cntMoney=0;
for(int i=1;i<n;i++) {
if(cntBS>=arr[i][0]&&arr[i][1]>arr[i][0]) {
cntMoney+=arr[i][1];
cntBS-=arr[i][0];
}else {
cntBS+=arr[i][2];
if(cntBS>m)cntBS=m;
}
}
cntMoney+=cntBS;
System.out.print(cntMoney);
}
}
第三题
有一条长度为n*10e1000的彩带 彩带的每一个位置有一个价值 ai
小红的彩带是由一条长度为n的彩带一直循环得到的 i>n时 ai=ai-n
小红每次会从左往后或从右往左剪一段长度为x的彩带 想知道每次剪下来的彩带的价值和是多少
输入
6 3
1 1 4 5 1 4
L 2
L 3
R 12
输出
2
10
32
当时感觉是队列题
但是因为被第一题和第二题卡太长时间了
没时间写
赛后复盘
也请教了学校的acmer
感觉难度赶得上牛客周赛的d和e
import java.util.Scanner;
public class Main {
static final int N = 200005;
static long[] a = new long[N];
static long[] pre = new long[N];
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int t = 1;
while (t-- > 0) {
long n = scanner.nextLong();
long q = scanner.nextLong();
for (int i = 1; i <= n; ++i) {
a[i] = scanner.nextLong();
pre[i] = pre[i - 1] + a[i];
}
long l = 0;
long r = n + 1;
for (int i = 0; i < q; ++i) {
char op = scanner.next().charAt(0);
long num = scanner.nextLong();
long res = 0;
long cnt = num / n;
res += cnt * pre[n];
num = num % n;
if (num == 0) {
System.out.println(res);
continue;
}
if (op == 'L') {
if (l + num >= n) {
res += pre[n] - pre[(int)l];
l = l + num - n;
res += pre[(int)l];
} else {
res += pre[(int)(l + num)] - pre[(int)l];
l += num;
}
} else { // op == 'R'
if (num >= r - 1) {
res += pre[(int)(r - 1)];
r = r - num + n;
res += pre[n] - pre[(int)(r - 1)];
} else {
res += pre[(int)(r - 1)] - pre[(int)(r - num - 1)];
r -= num;
}
}
System.out.println(res);
}
}
scanner.close();
}
}
第四题
有一棵n节点的数
每个节点是红色或者白色
删除一个节点后 最大红色联通块的结点个数最小值是多少啊
第一行输入一个整数n表示节点的数量
第二行输入一个长度为n的字符串s表示节点的颜色
第i个节点的颜色为si w为白色 r为红色
接下来n-1行每行输入两个整数u v 标配是树上的边
直接放弃了...
总结
感觉题目还是很难的
对于我们这种不是专门搞算法的人来说
对数据结构考察
还有优化 降低时间复杂度
这次笔试 太慌张了 感觉就是想做很多 然后结果就做了一点点 下次死磕一题全对的就好了
还得继续学习
加油
#你的秋招第一场笔试是哪家#来源于自己的记录但是并不都是自己的面试经历 所有解答均是主观看法一个字一个字的敲的...

