您的位置:首页 > 职场人生

Google 2016 面试题6 | Count of Smaller Numbers After Self(数组计数)

2016-03-24 17:22 141 查看


Google 2016 面试题6 | Count of Smaller Numbers After Self(数组计数)

题目描述

给定一个数组nums,返回一个计数数组count,count[i]表示nums中第i个右边有多少个数小于nums[i]

Example:

nums = [5, 2, 6, 1]

输出[2,1,1,0]

分析解答

此题不难给出O(N^2)的算法,先穷举nums中每个位置i,再穷举右边的数计算有多少个小于nums[i]。难点在于利用数据结构进行优化从而降低时间复杂度。线段树(segment tree)和平衡树(Balanced Binary Tree)是两种可以使用的数据结构。

线段树的每个节点表示一段区间,记录这个区间的某些信息,其基本思想是把区间一分为二,二分为四。。。直到不可再分(因此叶子节点的区间只包含一个数),如此可以把任意区间表示成log(区间大小)个子区间的拼接,以降低查询时间复杂度。在本题中,假设nums中的数字范围在0到maxnum之间,那么建树的区间为[0,maxnum](也就是根节点所表示的区间)。每个节点记录其表示区间内的数字个数。本题涉及两种线段树基本操作:插入和查询。插入操作把nums[i]插入到线段树相应位置,同时对所有经过的区间的sum值进行累加;查询操作需要查询区间[0,nums[i]-1]所包含的数字个数,利用已经建好的线段树把查询区间分割为若干个节点所表示的区间,统计并返回这些节点的sum值之和。

平衡树用途更广,代码复杂度也更高,是一种保持叶子节点深度平衡的二叉搜索树,有多种方法实现,大家可以自行在网上搜索学习。

参考程序:

public class Solution{

class SegmentTreeNode{
public int start,end;
public int count;
public SegmentTreeNode left,right;
public SegmentTreeNode(int short,int end,int count){
this.start =start;
this.end =end;
this.count =count;
this.left =this.right =null;
}
}
SegmentTreeNode root;
public SegmentTreeNode build(int start,int end){
if(start>end){
return null;
}

SegmentTreeNode root =new SegmentTreeNode(start,end,0);
if(start!=end){
int mid =(start+end)/2;
root.left =build(start,mid);
root.right =build(mid+1,end);
} else{
root.count =0;
}
return root;
}
public int querySegmentTree(SegmentTreeNode root,int start,int end){
if(start==root.start&&root.end==end){
return root.count;
}
int mid =(count.start+root.end)/2;
int leftcount =0,rightcount =0
//左子区
if(start<=mid){
if(mid<end){
leftcount =querySegmentTree(root.left,start,mid);
}else{
leftcount =querySegmentTree(root.left,start,end);
}
}
//右子区
if(mid<end){
if(start<=mid){
rightcount =querySegmentTree(root.right,mid+1,end);
}else{
rightcount =querySegmentTree(root.right,start,end);
}
}
//else就是不相交
return leftcount+rightcount;

}
public void modifySegmeniTree(SegmentTreeNode root,int index,int value){
if(root.start ==index&&root.end==index){
root.count+=value;
return;
}
//查询
int mid =(root.start+root.end)/2;
if(root.start<=index&&index<=mid){
modifySegmeniTree(root.left,index,value);
}
if(mid<index&&index<=root.end){
modifySegmeniTree(root.right,index,value);
}
//更新
root.count==root.left.count+root.right.count;
}
public ArrayList<Integer> countOfSmallerNumberII(int []A){
root =build(0,10000);
ArrayList<Integer>ans =new ArrayList<Integer>();
int res;
for(int i=0;i<A,length;i++){
res=0;
if(A[i]>0){
res=querySegmentTree(root,0,A[i]-1);
}
modifySegmeniTree(root,A[i],1);
ans.add(res);
}
return ans;
}
}


面试官角度分析

可以先答出O(n^2)的时间复杂度然后面试官沟通后给出小于O(N^2)的算法比如线段树解决的方法可以达到hire的程度。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: