题目大意:
统计不开心的朋友
给你一份 n
位朋友的亲近程度列表,其中 n
总是 偶数 。
对每位朋友 i
,preferences[i]
包含一份 按亲近程度从高到低排列 的朋友列表。换句话说,排在列表前面的朋友与 i
的亲近程度比排在列表后面的朋友更高。每个列表中的朋友均以 0
到 n-1
之间的整数表示。
所有的朋友被分成几对,配对情况以列表 pairs
给出,其中 pairs[i] = [xi, yi]
表示 xi
与 yi
配对,且 yi
与 xi
配对。
但是,这样的配对情况可能会是其中部分朋友感到不开心。在 x
与 y
配对且 u
与 v
配对的情况下,如果同时满足下述两个条件,x
就会不开心:
x
与u
的亲近程度胜过x
与y
,且u
与x
的亲近程度胜过u
与v
返回 不开心的朋友的数目 。
示例 1:
输入:n = 4, preferences = [[1, 2, 3], [3, 2, 0], [3, 1, 0], [1, 2, 0]], pairs = [[0, 1], [2, 3]] 输出:2 解释: 朋友 1 不开心,因为: - 1 与 0 配对,但 1 与 3 的亲近程度比 1 与 0 高,且 - 3 与 1 的亲近程度比 3 与 2 高。 朋友 3 不开心,因为: - 3 与 2 配对,但 3 与 1 的亲近程度比 3 与 2 高,且 - 1 与 3 的亲近程度比 1 与 0 高。 朋友 0 和 2 都是开心的。
示例 2:
输入:n = 2, preferences = [[1], [0]], pairs = [[1, 0]] 输出:0 解释:朋友 0 和 1 都开心。
示例 3:
输入:n = 4, preferences = [[1, 3, 2], [2, 3, 0], [1, 3, 0], [0, 2, 1]], pairs = [[1, 3], [0, 2]] 输出:4
提示:
2 <= n <= 500
n
是偶数preferences.length == n
preferences[i].length == n - 1
0 <= preferences[i][j] <= n - 1
preferences[i]
不包含i
preferences[i]
中的所有值都是独一无二的pairs.length == n/2
pairs[i].length == 2
xi != yi
0 <= xi, yi <= n - 1
- 每位朋友都 恰好 被包含在一对中
前言:
最近很多朋友私信我,问到为什么最近博客更新变少了?这里统一回复一下,真的非常抱歉,最近接了一个私活,项目很大,而且是从零开始的那种。从项目架构到云服务器搭建,以及数据库设计,api设计,web端,app端甚至各种小程序端都有所涉及。事无巨细,全部亲力亲为,因此实在难以抽出时间来更新刷题博客。这个项目中运用到的技术也很广泛,总结了一下,大概包括以下内容:
SpringBoot,SpringSecurity,MyBatis,MyBatisGenerator,PageHelper,Swagger,Hibernator-Validator,Elasticsearch,RabbitMQ,Redis,MongoDB,Docker,Druid,OSS,JWT,LogStash,Lombok
Vue,Vue-router,Vuex,Element,Axios,v-charts,Js-cookie,nprogress
Android,iOS,MVVM,rx等
如果有时间的话,也很想和大家分享一下目前这个私活中学到的一些知识,希望能对大家有所帮助。虽然项目很忙,但今后我还会每周参加leetcode周赛,并尽量保持每周更新一些周赛题目的讲解。此外本网站的题目还会保持更新,大家可以随时查看leetcode每道题目的公司tag以及加锁题目内容。以下言归正传:
如果想查看本题目是哪家公司的面试题,请参考以下免费链接: https://leetcode.jp/problemdetail.php?id=1583
解题思路分析:
个人觉得这道题目的描述并不是那么清晰,题目中说,
在 x
与 y
配对且 u
与 v
配对的情况下,如果同时满足下述两个条件,x
就会不开心:
x
与u
的亲近程度胜过x
与y
,且u
与x
的亲近程度胜过u
与v
如果将条件完整描述一下,应该是下面这样子:
x
与u
的亲近程度胜过x
与y
,且u
与x
的亲近程度胜过u
与v
或者
x
与v
的亲近程度胜过x
与y
,且v
与x
的亲近程度胜过v
与u
的情况下x会刚到不开心。
此外,
y
与v
的亲近程度胜过y
与x
,且v
与y
的亲近程度胜过v
与u
或者
y
与u
的亲近程度胜过y
与x
,且u
与y
的亲近程度胜过u
与v
的情况下y会刚到不开心。
单纯看上面的条件你可能会蒙掉,这里简单总结一下即是:对于任意两个分组,如果其中一个人在另一组中有个相好的,即这个人与那个相好的关系要好于本组中的另一人,同时,那个相好的与这个人的关系也好于他同组的另一个人时,此时当前人是不开心的。返回结果应该加一,不过这里需要注意一点,这个人在和其他组的比较中可能已经存在其他不开心的组合,因此这里的计数或许会出现重复累加的情况,解决这个问题我们可以使用一个访问数组,来记录下哪些人已经是不开心的状态,再遇到此人不开心时,不要重复计数。
接下来说下解题过程:
- 首先,将其他所有人在每个人心目中的亲密关系排行记录一下,我们使用一个二维的数组:int[][] happyMap; 数组的一维下标代表每个人的编号,二维下标则是该人在当前人心目中的亲近排行。因此,我们happyMap[v][x]代表了,x在v心中的地位,数字越小,地位越靠前。
- 定义一个访问数组,记录下已经标记为不开心的人。
- 二层循环,遍历比较每两组人。统计不开心的人数(注意使用访问数组排重)。
实现代码:
public int unhappyFriends(int n, int[][] preferences, int[][] pairs) { int[][] happyMap = new int[n][n]; // 每个人心中其他人的亲密度排行 for(int i=0;i<preferences.length;i++){ // 循环每个人 for(int j=0;j<preferences[i].length;j++){ // 循环其他人 happyMap[i][preferences[i][j]]=j; // j在i心中的排行为当前顺位 } } int res=0; // 返回结果 boolean[] visited = new boolean[n]; // 标记不开心的人 for(int i=0;i<pairs.length;i++){ // 循环每一组 int x=pairs[i][0]; // x同学 int y=pairs[i][1]; // y同学 for(int j=0;j<pairs.length;j++){ // 循环另一组 if(i==j) continue; // 两组相同时,跳过 int u=pairs[j][0]; // u同学 int v=pairs[j][1]; // v同学 // 如果x还未标记为不开心,并且 // x与u的关系好于x与y,并且u与x的关系好于u与v // 或者x与v的关系好于x与y,并且v与x的关系好于v与u if(!visited[x]&&(happyMap[x][u]<happyMap[x][y] &&happyMap[u][x]<happyMap[u][v]|| happyMap[x][v]<happyMap[x][y] &&happyMap[v][x]<happyMap[v][u])){ visited[x]=true; // x同学不开心 res++; // 返回结果加一 } // 如果y还未标记为不开心,并且 // y与v的关系好于y与x,并且v与y的关系好于v与u // 或者y与u的关系好于y与x,并且u与y的关系好于u与v if(!visited[y]&&(happyMap[y][v]<happyMap[y][x] &&happyMap[v][y]<happyMap[v][u] ||happyMap[y][u]<happyMap[y][x] &&happyMap[u][y]<happyMap[u][v])){ visited[y]=true; // y同学不开心 res++; // 返回结果加一 } } } return res; }
本题解法执行时间为7ms。
Runtime: 7 ms, faster than 100.00% of Java online submissions for Count Unhappy Friends.
Memory Usage: 60.8 MB, less than 60.00% of Java online submissions for Count Unhappy Friends.
本网站文章均为原创内容,并可随意转载,但请标明本文链接如有任何疑问可在文章底部留言。为了防止恶意评论,本博客现已开启留言审核功能。但是博主会在后台第一时间看到您的留言,并会在第一时间对您的留言进行回复!欢迎交流!
本文链接: https://leetcode.jp/leetcode-1583-count-unhappy-friends-解题思路分析/