lintcode 998 · 构造队列 【hard vip 线段树】

题目链接,描述

https://www.lintcode.com/problem/998

java 复制代码
给定两个数组 arr1 和 arr2, 它们的长度都是 n. arr1 中的元素互不相同.

现在你需要构造 arr1 的另一个排列. 在这个排列中, 数字 arr1[i] 前面有 arr2[i] 个数比它小.

1≤n≤10的5次方


样例
样例 1:

输入: 
    n = 5, 
    arr1 = [1, 2, 3, 4 ,5], 
    arr2 = [0, 0, 0, 1, 3]
输出: [3, 4, 2, 5, 1]
解释: 
    在 [3, 4, 2, 5, 1] 中, 在 1 之前没有比它自己还小的元素, 2 和 3 也是如此.
    在 4 前面有一个 3 比它小.
    在 5 前面有 3, 4 和 2 比它小.
样例 2:

输入: 
    n = 4,
    arr1 = [1, 3, 7, 6],
    arr2 = [0, 1, 3, 2]
输出: [1, 3, 6, 7]
解释: 
    1 前面没有元素.
    3 前面有一个 1 比它小.
    7 前面的 3 个元素都比它小.
    6 前面有 1 和 3 比它小.

思路

前置知识:线段树;

本题是比较难的

解题步骤:

先将所有点按从大到小的顺序排列,然后从最大的开始插入到线段树中。

对于区间[l,mid],[mid+1,r]。满足[l,mid]中未被填充的数字比比它自身小的数的个数大,

则继续搜索左区间,反之搜索右区间。填充,更新即可。 时间复杂度为O(nlogn)O(nlogn)。

答案

java 复制代码
public class Solution {
    /**
     * @param n: The array sum
     * @param arr1: The size
     * @param arr2: How many numbers smaller than itself 
     * @return: The correct array
     */
    public int[] getQueue(int n, int[] arr1, int[] arr2) {
        /*
    先将所有点按从大到小的顺序排列,然后从最大的开始插入到线段树中。
    对于区间[l,mid],[mid+1,r]。满足[l,mid]中未被填充的数字比比它自身小的数的个数大,
    则继续搜索左区间,反之搜索右区间。填充,更新即可。       时间复杂度为O(nlogn)O(nlogn)。
     */
        Info[] arr = new Info[100000+10];
        for (int i = 0; i < n; i++) {
            arr[i] = new Info(arr1[i],arr2[i]);
        }

        Arrays.sort(arr,0,n, new Comparator<Info>() {
            @Override
            public int compare(Info a, Info b) {
                return b.data-a.data;
            }
        });

        int[] ans = new int[n];
        Node root = build(1,n);
        for (int i = 0; i <n ; i++) {
            int pos = query(root,arr[i].cnt+1);
            ans[pos-1]= arr[i].data;
        }

        return ans;
    }

    static class Info{
        int data;//值
        int cnt; //有几个值比自己小
        public Info(int d ,int c){
            data =d;
            cnt =c;
        }
    }

    static class Node{
        int start,end,sum;
        Node left,right;
        public Node(int s,int e){
            start = s;
            end=e;
            sum =0;
            left = null;
            right =null;
        }
    }

    public static Node build(int start,int end){
        if(start >end) return null;
        if(start ==end){
            Node nn = new Node(start,end);
            nn.sum =1;
            return nn;
        }

        Node root = new Node(start,end);
        int m = start+(end-start)/2;
        root.left = build(start,m);
        root.right = build(m+1,end);
        root.sum =0;

        if(root.left!=null)
            root.sum+= root.left.sum;
        if(root.right!=null)
            root.sum+=root.right.sum;
        return root;
    }

    public static int query(Node root,int k){
        if(root.start > root.end) return 0;
        if(root.start == root.end){
            root.sum =0;
            return root.start;
        }

        int ans =0;
        if(k<=root.left.sum){
            ans = query(root.left,k);
        }else{
            ans = query(root.right,k-root.left.sum);
        }

        root.sum =0;
        if(root.left!=null)
            root.sum+= root.left.sum;

        if(root.right!=null)
            root.sum += root.right.sum;

        return ans;

    }

}
相关推荐
魔道不误砍柴功14 分钟前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_23414 分钟前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
pianmian115 分钟前
python数据结构基础(7)
数据结构·算法
闲晨17 分钟前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
测开小菜鸟2 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
好奇龙猫2 小时前
【学习AI-相关路程-mnist手写数字分类-win-硬件:windows-自我学习AI-实验步骤-全连接神经网络(BPnetwork)-操作流程(3) 】
人工智能·算法
P.H. Infinity3 小时前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天3 小时前
java的threadlocal为何内存泄漏
java
sp_fyf_20243 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
caridle3 小时前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express