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 标配是树上的边
直接放弃了...
总结
感觉题目还是很难的
对于我们这种不是专门搞算法的人来说
对数据结构考察
还有优化 降低时间复杂度
这次笔试 太慌张了 感觉就是想做很多 然后结果就做了一点点 下次死磕一题全对的就好了
还得继续学习
加油
#你的秋招第一场笔试是哪家#