315. Count of Smaller Numbers After Self#
开篇闲话:
两天没有刷题,前天白天复习了一遍jvm,晚上跟女朋友出去吃晚饭,回来就没心思敲代码,所以想干脆整理一下背包问题,博客链接—动态规划–背包问题;
昨天晚上,实习公司因为为期六个月的实习项目终于完美落幕了,所以三个小组共同去撸串吃猪腰子了(听说是大补,哈哈哈),虽然直到离开,我也不清楚哪串肉,但玩的很开心,特别是中间,组长突然叫住我,跟我说,项目答辩的时候,我原来那个小组的组长(黄**组长)还夸我技术不错,基础扎实,你要好好保持学习下去,深入理解那些架构,哇,突然被夸,有点小激动,说不出的喜悦,赶紧回答,会的会的(哈哈哈,遗憾的是,可能太开心,竟然忘记向组长敬杯酒了)。感谢小组六个月的照顾,第一份实习,大家相处都很开心、融洽。
1. 题目描述
题目链接
You are given an integer array nums and you have to return a new counts array. The counts array has the property where counts[i] is the number of smaller elements to the right of nums[i].
Example:
Input: [5,2,6,1]
Output: [2,1,1,0]
Explanation:
To the right of 5 there are 2 smaller elements (2 and 1).
To the right of 2 there is only 1 smaller element (1).
To the right of 6 there is 1 smaller element (1).
To the right of 1 there is 0 smaller element.
2. 题目分析
因为一开始没有想法,动态规划不行,感觉不管怎样,每次都需要遍历一遍当前数值右边的所有数,才能找到比它小的数字,所以直接上暴力破解,但提交后发现超时,哈哈哈,心疼的抱着傻乎乎的自己。
3. 解决思路
参见网上的想法,原来可以从右边开始遍历,同时不断把已经遍历过的数字放到另外一个sort数组中,并且对这个sort数组进行升序存储,所以,如果要找当前数值右边有几个比它小的个数,那么就是要找到当前数值应该放入到sort数组中的位置(为了提高效率,使用二分查找法来确定当前数值应该放入的位置),即是它右边有几个比它小的个数。
example:
nums: [5,2,6,1]
当i = 3,nums[i] =1,sort[0]=nums[i];
当i = 2,nums[i] =6,通过在sort(目前只有元素1)中使用二分法查找,发现6应该插入到1后面,即index=1,sort[index]=nums[i];所以当前值6右边比它小的数字的个数为index=1
0 | 1 | 2 | 3 |
---|---|---|---|
1 | 6 |
当i = 1,nums[i] =2,通过在sort(目前只有元素1,6)中使用二分法查找,发现2应该插入到1后面,即index=1,sort[index]=nums[i];所以当前值2右边比它小的数字的个数为index=1
0 | 1 | 2 | 3 |
---|---|---|---|
1 | 2 | 6 |
当i = 0,nums[i] =5,通过在sort(目前只有元素1,6,2)中使用二分法查找,发现5应该插入到2后面,即index=2,sort[index]=nums[i];所以当前值5右边比它小的数字的个数为index=2
0 | 1 | 2 | 3 |
---|---|---|---|
1 | 2 | 5 | 6 |
则,结果为Output: [2,1,1,0]
4. 代码实现(java)
package com.algorithm.leetcode.greedy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created by 凌 on 2018/12/22.
* 描述:315. Count of Smaller Numbers After Self
*/
public class CountSmaller {
public static void main(String[] args) {
int[] nums = {5,2,6,1};
List<Integer> result = countSmaller(nums);
for(Integer value : result){
System.out.printf(value + "\t");
}
}
public static List<Integer> countSmaller(int[] nums) {
if(nums == null){
return new ArrayList<Integer>();
}
Integer[] result = new Integer[nums.length];
//对已经遍历的右边的数值进行升序存储,找到当前数值应该放入的位置,即是它右边有几个比它小的个数
List<Integer> sort = new ArrayList<Integer>(nums.length);
int left,right;
int mid;
for(int i=nums.length - 1;i >= 0;i--){
left = 0;
right = sort.size();
//二分法查到当前数值的排序位置,即当前数值的右边有几个比它小的个数
while (left < right){
mid = left + (right - left)/2;
if (sort.get(mid) >= nums[i]){
right = mid;
}else{
left = mid + 1;
}
}
result[i] = left;
sort.add(left, nums[i]);
}
return Arrays.asList(result);
}
}