319weekly-3 逐层排序二叉树所需的最少操作数目

题目描述

给你一个值互不相同的二叉树的根节点 root 。

在一步操作中,你可以选择同一层上任意两个节点,交换这两个节点的值。

返回每一层按严格递增顺序排序所需的最少操作数目。

节点的层数是该节点和根节点之间的路径的边数。

输入:root = [1,4,3,7,6,8,5,null,null,null,null,9,null,10]
输出:3
解释:

  • 交换 4 和 3 。第 2 层变为 [3,4] 。
  • 交换 7 和 5 。第 3 层变为 [5,6,8,7] 。
  • 交换 8 和 7 。第 3 层变为 [5,6,7,8] 。
    共计用了 3 步操作,所以返回 3 。
    可以证明 3 是需要的最少操作数目。

解体思路

首先分析题目,该题一共需要解决两个问题

  • 第一个问题为树的层序遍历,
  • 第二个问题为无序数组到有序数组的最小操作数
层序遍历的解决
  • 采用链表保存节点的方式
// 层序遍历
List<TreeNode> nodelist = new LinkedList<>();
nodelist.add(root);
while(nodelist.size() != 0) {
    int len = nodelist.size();
    for(int i = 0; i < len; ++i) {
        TreeNode node = nodelist.remove(0);
        if(node.left != null) 
            nodelist.add(node.left);
        if(node.right != null) 
            nodelist.add(node.right);
    }
}
无序数组到有序数组的最小操作数
  • 是一个经典问题,通过比较交换的方式来找到最小的操作次数
  • 每当遇到一个不在该位置的数时,通过循环查找的方式(简单理解为,当前位置数值不对时,相对应有最少一个数位置不对)找到该数值应该在的位置。
  • 该题的重点是怎么妥善的保存有序数组的下标。采用的方式是用一个hashmap来记录
// hashmap 记录有序数组的下标
for(int i = 0; i < len; ++i) {
    map.put(sortnums[i], i);
}
// 循环查找该数值的正确位置
for(int i = 0; i < len; ++i) {
    if(sortnums[i] != nums[i]) {
        int temp = i;
        ans = 0;
        while(sortnums[i] != nums[temp]) {
            int t = temp;
            temp = map.get(nums[temp]);
            nums[t] = sortnums[t];
            ans++;
        }
        nums[temp] = sortnums[temp];
        res += ans;
    }
}
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */

class Solution {
    public int minimumOperations(TreeNode root) {
        List<TreeNode> nodelist = new LinkedList<>();
        nodelist.add(root);
        int res = 0;
        while(nodelist.size() != 0) {
            int len = nodelist.size();
            int[] nums = new int[len];
            int[] sortnums = new int[len];
            Map<Integer, Integer> map = new HashMap<>();
            for(int i = 0; i < len; ++i) {
                TreeNode node = nodelist.remove(0);
                nums[i] = node.val;
                sortnums[i] = node.val;
                if(node.left != null) 
                    nodelist.add(node.left);
                if(node.right != null) 
                    nodelist.add(node.right);
            }
            int ans = 0;
            Arrays.sort(sortnums);
            for(int i = 0; i < len; ++i) {
                map.put(sortnums[i], i);
            }
            for(int i = 0; i < len; ++i) {
                if(sortnums[i] != nums[i]) {
                    int temp = i;
                    ans = 0;
                    while(sortnums[i] != nums[temp]) {
                        int t = temp;
                        temp = map.get(nums[temp]);
                        nums[t] = sortnums[t];
                        ans++;
                    }
                    nums[temp] = sortnums[temp];
                    res += ans;
                }
            }
        }
        
        return res;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值