维护x的秩
维护x的秩
题目描述
现在我们要读入一串数,同时要求在读入每个数的时候算出它的秩,即在当前数组中小于等于它的数的个数(不包括它自身),请设计一个高效的数据结构和算法来实现这个功能。
给定一个int数组A,同时给定它的大小n,请返回一个int数组,元素为每次加入的数的秩。保证数组大小小于等于5000。
测试样例:
[1,2,3,4,5,6,7],7
返回:[0,1,2,3,4,5,6]
思路:
链接:https://www.nowcoder.com/questionTerminal/0ade0d95c85349beb934a90b1d9b02be?f=discussion
来源:牛客网
用一个二叉查找树来维护当前已经插入的数组,小于等于该节点插入左子树内,
大于插入右子树内,递归调用。
这样,每次查询小于等于某个节点的节点数,分三种情况讨论,递归调用:
1.当前节点的值等于插入的节点的值,那么返回该节点的左子树数目就等于秩
2.当前节点的值大于插入的节点的值,那么递归调用左子树(因为该节点的本身
及其右子树都对秩没影响)
3.当前节点的值小于插入的节点的值,那么当前节点的所有左子树加上本身都是
该插入节点的秩,
然后加上插入的节点在右子树中的秩之和为改插入节点的秩
注意:1.只用记录当前节点的左子树的个数,2.每次都是先插再找出秩,所以每
次查找不会出现不在树中的情况。
代码如下:
package com.jiading.niuke;
/**
* @program: Algorithm
* @description: 维护x的秩
* 现在我们要读入一串数,同时要求在读入每个数的时候算出它的秩,即在当前数组中小于等于它的数的个数(不包括它自身),请设计一个高效的数据结构和算法来实现这个功能。
* 给定一个int数组A,同时给定它的大小n,请返回一个int数组,元素为每次加入的数的秩。保证数组大小小于等于5000。
* @author: JiaDing
* @create: 2020-07-31 23:08
**/
public class Rank {
public static int[] getRankOfNumber(int[] A, int n) {
int[] ans = new int[n];
Node node = null;
for (int i = 0; i < n; i++) {
if (node == null) {
node = new Node(A[i]);
ans[i] = 0;
} else {
ans[i] = node.insert(A[i]);
}
}
return ans;
}
static class Node {
int leftSize = 0;
int val = 0;
Node left = null, right = null;
public Node(int val) {
this.val = val;
}
public int insert(int val) {
if (this.val <= val) {
if (this.right != null) {
return leftSize + 1 + this.right.insert(val);
} else {
this.right = new Node(val);
return this.leftSize + 1;
}
} else {
this.leftSize++;
if (this.left != null) {
return this.left.insert(val);
} else {
this.left = new Node(val);
return 0;
}
}
}
}
public static void main(String[] args) {
int[] rankOfNumber = getRankOfNumber(new int[]{5, 1, 7, 9, 3, 4, 2}, 7);
for (int i : rankOfNumber
) {
System.out.println(i);
}
}
}
有一点要注意,就是我们保留一个leftSize字段就可以了,没必要用rightSize字段,因为不可能用到这个值(leftSize只有比left都大的时候才用,但是没有很方便的方法测量是否比right的都大,所以没用)
在插入的时候其实就能把秩算出来了,没必要单独再计算一次

浙公网安备 33010602011771号