LeetCode破解之适龄朋友

127 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情

题目描述

在社交媒体网站上有 n 个用户。给你一个整数数组 ages ,其中 ages[i] 是第 i 个用户的年龄。

如果下述任意一个条件为真,那么用户 x 将不会向用户 y(x != y)发送好友请求:

  • ages[y] <= 0.5 * ages[x] + 7

  • ages[y] > ages[x]

  • ages[y] > 100 && ages[x] < 100

否则,x 将会向 y 发送一条好友请求。

注意,如果 x 向 y 发送一条好友请求,y 不必也向 x 发送一条好友请求。另外,用户不会向自己发送好友请求。

返回在该社交媒体网站上产生的好友请求总数。

示例 1:

输入:ages = [16,16] 输出:2 解释:2 人互发好友请求。

示例2

输入:ages = [16,17,18] 输出:2 解释:产生的好友请求为 17 -> 16 ,18 -> 17 。

桶计数

思路分析:从里面可以分析出来n <= 2 * 10^4,如果我们使用O(n^2)肯定就吃TE了,所以得优化时间复杂度,分析题目发现我们可以剪枝,以下条件时成立时,就不会出现用户 x 向用户 y(x != y)发送好友请求。

  • age[y] <= 0.5 * age[x] + 7
  • age[y] > age[x] age[y] > 100
  • && age[x] < 100

那么可以吧这些无效的重复的操作直接省略掉,再利用桶来计数,那么就可以大幅度降低时间复杂度。桶计数的具体步骤如下:

  • 首先创建两个数组,将计数数组ageCnt和累加计数数组ageSum,分别用来统计某年龄的人数和小于等于此年龄的人数。
  • 然后将ages中的age计次,放入ageCnt数组。计算小于等于年龄i的人数,放入数组ageSum。利用循环,计算对于每个年龄i会发送好友请求的人数,其中选择范围为(i*0.5+7 -- i),同时去掉自己,并乘以此年龄的人数。累加到答案res中。
class Solution {
      public int minSwapsCouples(int[] row) {
          int n = row.length/2;
          Union u = new Union(n);
          for(int i = 0; i < n; i++){
              u.connect(row[i*2]/2,row[i*2+1]/2);
          }

          return u.getPart();
      }

      class Union{
          int[] parent;
          int[] sizes;
          int total;
          public Union(int n){
              parent = new int[n];
              for(int i = 0; i < n; i++){
                  parent[i] = i;
              }
              sizes = new int[n];
              Arrays.fill(sizes,1);
              total = n;
          }

          public int getPart(){
              return sizes.length-total;
          }

          public void connect(int a, int b){
              int rootA = root(a);
              int rootB = root(b);
              if(rootA==rootB) return;
              if(sizes[rootA]>=sizes[rootB]){
                  sizes[rootA]+=sizes[rootB];
                  parent[rootB] = rootA;
              }else{
                  sizes[rootB]+=sizes[rootA];
                  parent[rootA] = rootB;
              }
              --total;
          }

          private int root(int a){
              while(parent[a]!=a){
                  parent[a] = root(parent[a]);
                  a = parent[a];
              }
              return a;
          }
      }
  }

最后

题目感觉有点绕,有几点要注意才行:

  1. 年龄相等也可以给同龄人发送请求
  2. 15岁以下不能交友