ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

LeetCode 2097. 合法重新排列数对

2021-12-09 20:33:57  阅读:289  来源: 互联网

标签:pairs end int 数对 2097 alls 重新排列 欧拉


LeetCode 2097. 合法重新排列数对

题目描述

给你一个下标从 0 开始的二维整数数组 pairs,其中 pairs[i] = [start_i, end_i]。如果 pairs 的一个重新排列,满足对每一个下标 i1 <= i < pairs.length)都有 end_{i-1} == start_{i},那么我们就认为这个重新排列是 pairs 的一个 合法重新排列

请你返回 任意一个 pairs 的合法重新排列。

注意:数据保证至少存在一个 pairs 的合法重新排列。

样例

输入:pairs = [[5,1],[4,5],[11,9],[9,4]]
输出:[[11,9],[9,4],[4,5],[5,1]]
解释:
输出的是一个合法重新排列,因为每一个 end_{i-1} 都等于 start_{i}。
end0 = 9 == 9 = start1 
end1 = 4 == 4 = start2
end2 = 5 == 5 = start3


输入:pairs = [[1,3],[3,2],[2,1]]
输出:[[1,3],[3,2],[2,1]]
解释:
输出的是一个合法重新排列,因为每一个 end_{i-1} 都等于 start_{i}。
end0 = 3 == 3 = start1
end1 = 2 == 2 = start2
重新排列后的数组 [[2,1],[1,3],[3,2]] 和 [[3,2],[2,1],[1,3]] 都是合法的。
示例 3:

输入:pairs = [[1,2],[1,3],[2,1]]
输出:[[1,2],[2,1],[1,3]]
解释:
输出的是一个合法重新排列,因为每一个 end_{i-1} 都等于 start_{i}。
end0 = 2 == 2 = start1
end1 = 1 == 1 = start2

限制

  • 1<= pairs.length <= 10^5
  • pairs[i].length == 2
  • 0 <= start_i, end_i <= 10^9
  • start_i != end_i
  • pairs 中不存在一模一样的数对。
  • 至少 存在 一个合法的 pairs 重新排列。

算法

(有向图的欧拉路径) \(O(n)\)

欧拉路径与欧拉回路性质回顾:

  1. 对于无向图,所有边都是连通的。
    • 存在欧拉路径的充分必要条件:度数为奇数的点只能有0或2个
    • 存在欧拉回路的充分必要条件:度数为奇数的点只能有0个
  2. 对于有向图,所有边都是连通。
    • 存在欧拉路径的充分必要条件:要么所有点的出度均等于入度;要么除了两个点之外,其余所有点的出度等于入度,剩余的两个点:一个满足出度比入度多1(起点),另一个满足入度比出度多1(终点)
    • 存在欧拉回路的充分必要条件:所有点的出度均等于入度。

欧拉路径的遍历算法描述:

dfs(u){
	while 从u的所有出边:
        删边;
		dfs(v);//扩展
	seq<-u;// 保存的是欧拉回路的倒序
}

最终 seq[]中存下的就是欧拉路径的倒序,为什么u再最后才加入?因为需要遍历完u的所有子节点才能把u压入进来,u是后面所有点的起点。

有向图:
每用一条边 删掉
无向图:
每用一条边标记对应的反向边(XOR技巧)
a→b
b→a

数组模拟连接表:编号成对的(0, 1) (2, 3)(4, 5)......,编号的0的反向边为0^1 = 1,编号的1的反向边为1^1 = 0, 编号2的反向边为2^1 = 3,编号的2的反向边为3^1 = 2 ......

i的反向边为 i^1

本题可以转化为输出整个有向图的欧拉路径,输入路径上的编号组成答案。

构图:对每个数对 \(e\_i = (x, y)\),构造一条有向边 \(x \to y\),属性为 \(i\)。注意需要离散化一下。

因为题意本身就有答案,起点的出度减入度等于 1 的点或者任意一点即可。从起点开始深度优先遍历整个图即可。

时间复杂度

  • 遍历所有点和边一次,故总时间复杂度为 \(O(n)\)。

空间复杂度

  • 需要 \(O(n)\) 的额外空间存储图,递归的系统栈,以及欧拉路相关的数据结构。

C++代码

const int N = 100005;
class Solution {
public:
    vector<int> alls;
    vector<pair<int, int>> g[N];
    vector<int> path;
    int deg[N];
    void dfs(int u, int prev){
        while(!g[u].empty()){
            int v = g[u].back().first, e = g[u].back().second;
            g[u].pop_back();
            dfs(v, e);
        }
        if(prev != -1){
            path.push_back(prev);
        }
    }
    vector<vector<int>> validArrangement(vector<vector<int>>& pairs) {
        for(auto x : pairs){
            alls.push_back(x[0]);
            alls.push_back(x[1]);
        }
        sort(alls.begin(), alls.end());
        alls.erase(unique(alls.begin(), alls.end()), alls.end());
        
        for(int i = 0; i < pairs.size(); i++){
            int x = lower_bound(alls.begin(), alls.end(), pairs[i][0]) - alls.begin();
            int y = lower_bound(alls.begin(), alls.end(), pairs[i][1]) - alls.begin();
            g[x].push_back({y, i});
            deg[x]++;
            deg[y]--;
        }
        int first = 0;
        for(int i = 0; i < alls.size(); i++){
            if(deg[i] == 1){
                first = i;
                break;
            }
        }
        dfs(first, -1);
        vector<vector<int>> res;
        for(int i = path.size() - 1; i >= 0; i--){
            res.push_back(pairs[path[i]]);
        }
        return res;
    }
};

标签:pairs,end,int,数对,2097,alls,重新排列,欧拉
来源: https://www.cnblogs.com/pxlsdz/p/15669102.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有