【刷穿 LeetCode】1583. 统计不开心的朋友 : 数据结构模拟题

简介: 【刷穿 LeetCode】1583. 统计不开心的朋友 : 数据结构模拟题

网络异常,图片无法展示
|


题目描述



这是 LeetCode 上的 1583. 统计不开心的朋友 ,难度为 中等


Tag : 「哈希表」、「模拟」


给你一份 n 位朋友的亲近程度列表,其中 n 总是偶数


对每位朋友 ipreferences[i] 包含一份 按亲近程度从高到低排列 的朋友列表。


换句话说,排在列表前面的朋友与 i 的亲近程度比排在列表后面的朋友更高。每个列表中的朋友均以 0n-1 之间的整数表示。


所有的朋友被分成几对,配对情况以列表 pairs 给出,其中 pairs[i] = [xi, yi] 表示 xiyi 配对,且 yixi 配对。


但是,这样的配对情况可能会是其中部分朋友感到不开心。在 xy 配对且 uv 配对的情况下,如果同时满足下述两个条件,x 就会不开心:


  • xu 的亲近程度胜过 xy,且
  • ux 的亲近程度胜过 uv


返回 不开心的朋友的数目 。


示例 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
  • 每位朋友都 恰好 被包含在一对中


模拟



模拟题,先将所有的 preferencespreferences 使用「哈希表套哈希表」的形式进行存储,存储格式为 {x : {y : score1}, {z : score12}, ... }


如果 xxyy 的亲密度要比 xxzz 的亲密度要高,则有 score1 > score2score1>score2。利用原本 preferences[i]preferences[i] 就是按照亲密度进行排序,我们可以对下标进行转换作为亲密数得分即可。


然后对所有的 pairspairs 进行遍历,统计所有的答案,注意一个小朋友只能被统计一次。


当然利用 nn 的数据范围,直接使用二维数组充当哈希表也是可以的(见 P2P2


代码:


class Solution {
    Map<Integer, Map<Integer, Integer>> map = new HashMap<>();
    public int unhappyFriends(int n, int[][] preferences, int[][] pairs) {
        int m = pairs.length;
        for (int i = 0; i < n; i++) {
            int[] p = preferences[i];
            Map<Integer, Integer> cur = new HashMap<>();
            for (int j = 0; j < n - 1; j++) cur.put(p[j], n - j);
            map.put(i, cur);
        }
        int ans = 0;
        for (int i = 0; i < m; i++) {
            int x = pairs[i][0], y = pairs[i][1];
            boolean xok = false, yok = false;
            for (int j = 0; j < m; j++) {
                if (i == j) continue;
                int u = pairs[j][0], v = pairs[j][1];
                if (!xok && check(x, y, u, v)) xok = true;
                if (!yok && check(y, x, u, v)) yok = true;
                if (xok && yok) break;
            }
            if (xok) ans++;
            if (yok) ans++;
        }
        return ans;
    }
    boolean check(int x, int y, int u, int v) {
        Map<Integer, Integer> xmap = map.get(x), ymap = map.get(y);
        Map<Integer, Integer> umap = map.get(u), vmap = map.get(v);
        if (xmap.get(u) > xmap.get(y) && umap.get(x) > umap.get(v)) return true;
        if (xmap.get(v) > xmap.get(y) && vmap.get(x) > vmap.get(u)) return true;
        return false;
    }
}
复制代码


代码:


class Solution {
    int N = 510;
    int[][] map = new int[N][N];
    public int unhappyFriends(int n, int[][] preferences, int[][] pairs) {
        int m = pairs.length;
        for (int i = 0; i < n; i++) {
            int[] p = preferences[i];
            for (int j = 0; j < n - 1; j++) map[i][p[j]] = n - j;
        }
        int ans = 0;
        for (int i = 0; i < m; i++) {
            int x = pairs[i][0], y = pairs[i][1];
            boolean xok = false, yok = false;
            for (int j = 0; j < m; j++) {
                if (i == j) continue;
                int u = pairs[j][0], v = pairs[j][1];
                if (!xok && check(x, y, u, v)) xok = true;
                if (!yok && check(y, x, u, v)) yok = true;
                if (xok && yok) break;
            }
            if (xok) ans++;
            if (yok) ans++;
        }
        return ans;
    }
    boolean check(int x, int y, int u, int v) {
        if (map[x][u] > map[x][y] && map[u][x] > map[u][v]) return true;
        if (map[x][v] > map[x][y] && map[v][x] > map[v][u]) return true;
        return false;
    }
}
复制代码


  • 时间复杂度:预处理出 map 的复杂度为 O(n^2)O(n2);遍历统计答案的复杂度为 O(n^2)O(n2)。整体复杂度为 O(n^2)O(n2)
  • 空间复杂度:O(n^2)O(n2)


最后



这是我们「刷穿 LeetCode」系列文章的第 No.1583 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。


在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。


为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:github.com/SharingSour…


在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。

相关文章
|
5天前
|
存储 算法 大数据
深入解析力扣170题:两数之和 III - 数据结构设计(哈希表与双指针法详解及模拟面试问答)
深入解析力扣170题:两数之和 III - 数据结构设计(哈希表与双指针法详解及模拟面试问答)
|
19天前
<数据结构>五道LeetCode链表题分析.环形链表,反转链表,合并链表,找中间节点.
<数据结构>五道LeetCode链表题分析.环形链表,反转链表,合并链表,找中间节点
22 1
|
22天前
|
存储 Java
JAVA数据结构刷题 -- 力扣二叉树
JAVA数据结构刷题 -- 力扣二叉树
23 0
|
26天前
|
算法
数据结构与算法⑮(第四章_下)二叉树OJ(力扣:144,965,104,110,226,100,101,572)(下)
数据结构与算法⑮(第四章_下)二叉树OJ(力扣:144,965,104,110,226,100,101,572)
10 1
|
26天前
|
算法 C++
数据结构与算法⑮(第四章_下)二叉树OJ(力扣:144,965,104,110,226,100,101,572)(上)
数据结构与算法⑮(第四章_下)二叉树OJ(力扣:144,965,104,110,226,100,101,572)
11 1
|
1月前
|
存储 算法
Leetcode 30天高效刷数据结构和算法 Day1 两数之和 —— 无序数组
给定一个无序整数数组和目标值,找出数组中和为目标值的两个数的下标。要求不重复且可按任意顺序返回。示例:输入nums = [2,7,11,15], target = 9,输出[0,1]。暴力解法时间复杂度O(n²),优化解法利用哈希表实现,时间复杂度O(n)。
27 0
|
1月前
[leetcode~数位动态规划] 2719. 统计整数数目 hard
[leetcode~数位动态规划] 2719. 统计整数数目 hard
|
1月前
|
算法 API DataX
二叉树(下)+Leetcode每日一题——“数据结构与算法”“对称二叉树”“另一棵树的子树”“二叉树的前中后序遍历”
二叉树(下)+Leetcode每日一题——“数据结构与算法”“对称二叉树”“另一棵树的子树”“二叉树的前中后序遍历”
|
1月前
|
算法 DataX
二叉树(中)+Leetcode每日一题——“数据结构与算法”“剑指Offer55-I. 二叉树的深度”“100.相同的树”“965.单值二叉树”
二叉树(中)+Leetcode每日一题——“数据结构与算法”“剑指Offer55-I. 二叉树的深度”“100.相同的树”“965.单值二叉树”
|
1月前
leetcode 2520 统计能整除数字的位数
leetcode 2520 统计能整除数字的位数
7 0