当前位置:   article > 正文

Leetcode - 周赛404

Leetcode - 周赛404

目录

一,3200. 三角形的最大高度

二,3201. 找出有效子序列的最大长度 I

三,3202. 找出有效子序列的最大长度 II

四,3203. 合并两棵树后的最小直径


一,3200. 三角形的最大高度

本题直接模拟,分别计算一下红蓝红和蓝红蓝的最大高度。

代码如下:

  1. class Solution {
  2. public int maxHeightOfTriangle(int red, int blue) {
  3. return Math.max(make(red, blue), make(blue, red));
  4. }
  5. int make(int a, int b){
  6. int i = 1;
  7. while(true){
  8. if(i%2==1){
  9. a -= i;
  10. }else{
  11. b -= i;
  12. }
  13. if(a < 0 || b < 0) return i-1;
  14. i++;
  15. }
  16. }
  17. }

二,3201. 找出有效子序列的最大长度 I

本题讲个简单的做法,(a+b)%2 = (a%2 + b%2)%2,就是看相邻的两个数是奇奇,偶偶,还是奇偶,所以可以分别求这三种情况,即奇数的个数,偶数的个数,以及奇偶相间的个数(这里直接贪心,不用分奇偶奇还是偶奇偶,直接看第一个数是奇数还是偶数就行),代码如下:

  1. class Solution {
  2. public int maximumLength(int[] nums) {
  3. int sum = 0, k = -1, cnt = 1;
  4. for(int i=0; i<nums.length; i++){
  5. nums[i] %= 2;
  6. if(k == -1) k = nums[i];
  7. else{
  8. if((k^nums[i])==1){
  9. k ^= 1;
  10. cnt++;
  11. }
  12. }
  13. sum += nums[i];
  14. }
  15. return Math.max(Math.max(sum, nums.length-sum), cnt);
  16. }
  17. }

三,3202. 找出有效子序列的最大长度 II

本题无法使用dfs记忆化来做,会超时,那么我们如何来写这道题呢?有这样一个性质,假设(a + b)%k = (b + c)%k,可以推出 (a + b - (b + c))%k = 0,(a - c)%k = 0,即a%k = c%k。结合本题题意,如果将nums中的所有值 % k,可以得出子序列中奇数项都相同,偶数项也都相同。

定义f[x][y]:以x,y结尾的最长子序列(这里的x,y都是nums[i]%k)。由上述结论可以得出下面的递推公式 f[x][y] = f[y][x] + 1,代码如下:

  1. class Solution {
  2. public int maximumLength(int[] nums, int k) {
  3. int ans = 1;
  4. int[][] f = new int[k][k];
  5. for(int x : nums){
  6. x %= k;
  7. for(int y=0; y<k; y++){
  8. f[y][x] = f[x][y] + 1;
  9. ans = Math.max(f[y][x], ans);
  10. }
  11. }
  12. return ans;
  13. }
  14. }

四,3203. 合并两棵树后的最小直径

写本题需要推出一个结论,就是该题的最长路径长度一定是e1的直径,e2的直径,e1的直径/2 + e2的直径/2 + 1 (即两个树直径的中点相连)这三者的最大值。

可以由反证法证明为啥是两个树直径的中点相连,存在两种情况:

  • 如果存在一个点不在e1或e2的直径上,那么以它相连得到的最长直径,一定要先走到直径上,所以它一定比两个树直径的中点相连多走一段距离
  • 如果存在一个点在e1或e2的直径上但是不是中点,显而易见,以它相连得到的最长直径一定要大于两个树直径的中点相连

得出结论后,我们要做的就是求出两个图的直径,代码如下:

  1. class Solution {
  2. public int minimumDiameterAfterMerge(int[][] e1, int[][] e2) {
  3. int s1 = inital(e1);
  4. int s2 = inital(e2);
  5. return Math.max(Math.max(s1, s2), (s1+1)/2 + (s2+1)/2 + 1);
  6. }
  7. int res;
  8. int inital(int[][] edge){
  9. int n = edge.length;
  10. List<Integer>[] g = new ArrayList[n+1];
  11. Arrays.setAll(g, e->new ArrayList<>());
  12. for(int[] e : edge){
  13. int x = e[0], y = e[1];
  14. g[x].add(y);
  15. g[y].add(x);
  16. }
  17. res = 0;
  18. dfs(0, -1, g);
  19. return res;
  20. }
  21. //求直径
  22. int dfs(int x, int fa, List<Integer>[] g){
  23. int maxLen = 0;
  24. for(int y : g[x]){
  25. if(y != fa){
  26. int t = dfs(y, x, g)+1;
  27. res = Math.max(res, maxLen + t);
  28. maxLen = Math.max(maxLen, t);
  29. }
  30. }
  31. return maxLen;
  32. }
  33. }

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号