携程笔试 08.30 AC
笔试有点简单啊,和美团第一次笔试一样
#校招##笔试##携程##23届秋招笔面经#
恶心,至今没面试
第二题
题目:
y,o,u 三个字母各有 a-b-c 个数,拼接成 you,加2分;每两个连续o,加一分。问最多可以多少分
解答:
ret = min(y. o. u) o = o - ret if o > 0: ret=ret+o-1
第三题
题目:
有一个无环图/树,每个节点可能是R或G或B。选择一条边将其删除,得到两个图,每个图都包含RGB节点。问能有几种删除方法。
解答:
有没有更好的方法呢!因为这个算是压着时间线过去的。
随机选择一个节点作为根结点(做的时候犯傻了,没必要选度为1的节点)
getColor 获得整个图 & 每个子树的RGB个数,即cnt。
checkDelete 查看每个边能否删除。
第四题
题目:
长度n的数组。可以选择数组中的某一个位置更新为任意值(也可以不更新),来获得最小的 max(abs(a[1]-a[0]), abs(a[2]-a[1]), .....)。
打印最小的值。
before: 1 10000 10 after: 1 5 10 结果:max(4, 5) = 5
解答:
比较繁琐的方法:
修改的位置有3种情况,0索引、n-1索引、其余索引。
对于其余索引 i 来说,value = 左侧sub的最大值,右侧sub的最大值,中间 arr[i-1], arr[i+1] 两者差值的一半。
左侧数组数组差值的最大值使用最大值栈来存储,右侧在遍历过程中更新rightMax就可以了。
另一种非常简单的方法是:
维护最大和第二大差值,以及他们所在的索引,然后进行处理,具体代码略。
// 比较麻烦的办法 public static void main4(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); long arr[] = new long[n]; for(int i = 0; i < n; i++) { arr[i] = sc.nextLong(); } long sub[] = new long[n-1]; for(int i = 0; i < n-1; i++) { sub[i] = Math.abs(arr[i] - arr[i+1]); } if(n == 2){ System.out.println(0); return; } // 最大栈 Stack<Long> s = new Stack<>(); s.add(0L); for(int i = 0; i < n-1; i++) { s.add(Math.max(s.peek(), sub[i])); } // n-1 状态 long rightMax = 0; s.pop(); long ret = s.peek(); // n-2 状态 for(int i = n-2; i >= 1; i--) { s.pop(); // s.peek() 左侧的最大值 // rightMax 右侧最大值 // 剩余中间的 ret = Math.min(ret, Math.max( Math.max(s.peek(), rightMax), (int)(Math.abs(arr[i+1]-arr[i-1]) + 1)/2)); rightMax = Math.max(rightMax, sub[i]); } // 0 状态 ret = Math.min(ret, rightMax); System.out.println(ret); }