一、题目分析
count[i]表示在nums[i]右侧且比它小的元素个数
下面是构造成树的思路
yi
还有一种方法是归并排序
二、代码
方法1:搜索二叉树
class TreeNode {
int val;
int size;
TreeNode left, right;
TreeNode(int val) {
this.val = val;
}
}
public class Solution {
TreeNode root;
private int smaller(TreeNode current, int val) {
current.size ++;
if (current.val < val) {
if (current.right == null) current.right = new TreeNode(val);
return current.size - 1 - current.right.size + smaller(current.right, val);
} else if (current.val > val) {
if (current.left == null) current.left = new TreeNode(val);
return smaller(current.left, val);
} else {
return current.left == null? 0 : current.left.size;
}
}
public List<Integer> countSmaller(int[] nums) {
List<Integer> result = new ArrayList<>(nums.length);
int[] smaller = new int[nums.length];
if (nums == null || nums.length == 0) return result;
root = new TreeNode(nums[nums.length-1]);
for(int i=nums.length-1; i>=0; i--) {
smaller[i] = smaller(root, nums[i]);
}
for(int i=0; i<smaller.length; i++) result.add(smaller[i]);
return result;
}
}
这里是插入过程分成两种,一个是插入值小于当前值,一个是插入值大于当前值 ,如果相等就没有插入,而是直接返回一个值。当前结点的左子树为空返回0,否则返回左子树的结点个数
然后前面的current.size++不好理解,我理解成每次来一个结点,先在current结点的size++,表示这个节点下连着的节点的个数,包括自己。所以val(待插入节点的值)大于current.val,要向右子树插入,如果右子树为空,直接插入,否则递归查找到位置,返回值中current.size-1是因为减去当前还没有插入的节点,当前结点.size-1,再减去cu.right.size,就是right左边有几个节点小于right.val
方法2:归并排序
public class Solution {
private void sort(int[] nums, int[] smaller, int[] pos, int from, int to) {
if (from >= to) return;
int m = (from + to) / 2;
sort(nums, smaller, pos, from, m);
sort(nums, smaller, pos, m+1, to);
int[] merged = new int[to-from+1];
int i=from, j=m+1, k=0, jump = 0;
while (i<=m || j<=to) {
if (i>m) {
//jump ++;
merged[k++] = pos[j++];
} else if (j>to) {
smaller[pos[i]] += jump;
merged[k++] = pos[i++];
} else if (nums[pos[i]] <= nums[pos[j]]) {
smaller[pos[i]] += jump;
merged[k++] = pos[i++];
} else {
jump ++;
merged[k++] = pos[j++];
}
}
for(int p=0; p<merged.length; p++) pos[from+p] = merged[p];
}
public List<Integer> countSmaller(int[] nums) {
int[] smaller = new int[nums.length];
int[] pos =new int[nums.length];
for(int i=0; i<pos.length; i++) pos[i] = i;
sort(nums, smaller, pos, 0, nums.length-1);
List<Integer> result = new ArrayList<>(nums.length);
for(int i=0; i<nums.length; i++) result.add(smaller[i]);
return result;
}
}