Minimum Number of Operations to Sort a Binary Tree by Level
You are given the root of a binary tree with unique values.
In one operation, you can choose any two nodes at the same level and swap their values.
Return the minimum number of operations needed to make the values at each level sorted in a strictly increasing order.
The level of a node is the number of edges along the path between it and the root node.
Example 1:
Input: root = [1,4,3,7,6,8,5,null,null,null,null,9,null,10] Output: 3 Explanation: - Swap 4 and 3. The 2nd level becomes [3,4]. - Swap 7 and 5. The 3rd level becomes [5,6,8,7]. - Swap 8 and 7. The 3rd level becomes [5,6,7,8]. We used 3 operations so return 3. It can be proven that 3 is the minimum number of operations needed.
Example 2:
Input: root = [1,3,2,7,6,5,4] Output: 3 Explanation: - Swap 3 and 2. The 2nd level becomes [2,3]. - Swap 7 and 4. The 3rd level becomes [4,6,5,7]. - Swap 6 and 5. The 3rd level becomes [4,5,6,7]. We used 3 operations so return 3. It can be proven that 3 is the minimum number of operations needed.
Example 3:
Input: root = [1,2,3,4,5,6] Output: 0 Explanation: Each level is already sorted in increasing order so return 0.
Constraints:
- The number of nodes in the tree is in the range $[1, {10}^{5}]$.
- $1 \leq \text{Node.val} \leq {10}^{5}$
- All the values of the tree are unique.
解题思路
先bfs找出每一层的值,然后问题就变成了给定一个序列,可以交换任意两个位置的元素,最少需要进行多少次交换使得序列变成升序。
可把这个问题转换成一个环图。比如有原序列 2 1 4 5 3 ,这个序列对应的升序序列是 1 2 3 4 5 ,这时我们根据这两个序列进行建图,边$a \to b$表示升序序列的第$a$个位置的元素应该放到原序列的第$b$个位置,按照这种连边方式就会得到下图:
因为每个数都是不同的,因此每个数在原数组中以及排序后的数组中的位置是唯一确定的,因此每个点的入度和出度都是$1$,因此这个图就是一个环图。
如果交换的两个数不在同一个环里,那么会把这两个环合并成一个环。比如对原序列中第$2$个元素和第$3$个元素进行交换,原序列变成 2 4 1 5 3 ,就会得到下图:
如果交换的两个数在同一个环里,那么会把这个环裂开成两个环。比如对原序列中第$4$个元素和第$5$个元素进行交换,原序列变成 2 1 4 3 5 ,就会得到下图:
可以发现,对于一个升序序列,每一个数都是一个自环,一共有$n$个自环。因此为了实现最小的操作次数每次都应该把一个环裂开成两个环,直到变成$n$个环为止。因此一开始先统计环的个数,假设是$m$个环,由于每裂开一次最多增加一个环,因此至少要裂$n - m$次,即交换$n - m$次。
求一开始环的个数可以用并查集,由于这个是一个环图,一个环就是一个连通块,统计连通块的数量等价于统计环的数量。
AC代码如下:
1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode() : val(0), left(nullptr), right(nullptr) {} 8 * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 9 * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 10 * }; 11 */ 12 class Solution { 13 public: 14 int minimumOperations(TreeNode* root) { 15 queue<TreeNode*> q({root}); 16 int ret = 0; 17 while (!q.empty()) { 18 int sz = q.size(); 19 vector<int> a, fa; 20 while (sz--) { 21 auto t = q.front(); 22 q.pop(); 23 a.push_back(t->val); 24 if (t->left) q.push(t->left); 25 if (t->right) q.push(t->right); 26 } 27 28 unordered_map<int, int> mp; 29 for (int i = 0; i < a.size(); i++) { 30 fa.push_back(i); 31 mp[a[i]] = i; // 记录元素a[i]的下标位置 32 } 33 sort(a.begin(), a.end()); 34 35 function<int(int)> find = [&](int x) { 36 return fa[x] == x ? fa[x] : fa[x] = find(fa[x]); 37 }; 38 39 int cnt = 0; // 记录有多少个连通块被合并了,也就是需要破环的次数 40 for (int i = 0; i < a.size(); i++) { 41 int x = find(i), y = find(mp[a[i]]); 42 if (x != y) fa[x] = y, cnt++; 43 } 44 ret += cnt; 45 } 46 return ret; 47 } 48 };
这题是问对于一个序列可以交换任意两个位置的元素使其变成升序所需要的最小交换次数,可以用并查集来求解。如果只能交换相邻两个元素,那么就是统计序列中逆序对的数量,可以用树状数组或归并排序来求解。
参考资料
力扣第319场周赛:https://www.bilibili.com/video/BV1kY411Z7uE/
标签:Operations,Sort,right,TreeNode,level,int,Binary,序列,left From: https://www.cnblogs.com/onlyblues/p/16890211.html