面试金典系列--维护x的秩

来源:互联网 发布:瑞士军刀男 知乎 编辑:程序博客网 时间:2024/05/02 04:47

面试金典系列--维护x的秩


现在我们要读入一串数,同时要求在读入每个数的时候算出它的秩,即在当前数组中小于等于它的数的个数(不包括它自身),请设计一个高效的数据结构和算法来实现这个功能。

给定一个int数组A,同时给定它的大小n,请返回一个int数组,元素为每次加入的数的秩。保证数组大小小于等于5000。

测试样例:
[1,2,3,4,5,6,7],7
返回:[0,1,2,3,4,5,6]

直接暴力方法需要O(n^2)的时间复杂度,因此需要考虑更优的算法。

思路1:在加入第二个元素时,将前面的元素看出是已排序的数组,进行二分查找位置,这个位置就是其秩,然后将当前元素插入到有序数组中。这样每次查找时间降低为O(log n)。但是,进行元素的移动,每次的复杂度为O(n),总的复杂度也为O(n^2)。

基于此代码的解法如下:

import java.util.*;public class Rank {    public int[] getRankOfNumber(int[] A, int n) {        // write code here        int[] resu =new int[n];        resu[0]=0;        for(int i=1;i<n;i++){            int index=binarySearch(A,0,i-1,A[i]);            resu[i]=index;            int now = A[i];            for(int j=i;j>index;j--){            A[j]=A[j-1];            }            A[index]= now;        }        return resu;    }//第一个大于x的下标位置public int binarySearch(int[] a,int first,int last,int x){int low=first,high=last;while(low<=high){int mid=low+(high-low)/2;if(a[mid]<=x){low=mid+1;} else{high=mid-1;}}return low;}}

 思路2:既然上面思路是元素的移动带来的额外复杂度,考虑用树的结构来解决。

public class Rank {    Node root = null;     public int[] getRankOfNumber(int[] A, int n) {        int res[] = new int[n];        for (int i = 0; i < n; i++) {            res[i] = helper(A[i]);        }        return res;    }     public int helper(int a) {        if (root == null) {            root = new Node(a);        } else {            root.insert(a);        }        return root.getRank(a);    }} class Node {    int leftSize = 0;     Node left, right;    int val;     public Node(int v) {        val = v;    }     public void insert(int v) {        if (v <= val) {            if (left != null)                left.insert(v);            else                left = new Node(v);            leftSize++;        } else {            if (right != null)                right.insert(v);            else                right = new Node(v);        }    }     public int getRank(int v) {        if (v == val)            return leftSize;        if (v < val)            return left.getRank(v);        if (v > val)            return leftSize + 1 + right.getRank(v);        return 0;    }}





0 0
原创粉丝点击