LeetCode315—Count of Smaller Numbers After Self—Java版归并算法

这是我在研究leetcode的solution第一个解决算法时,自己做出的理解,并且为了大家能看懂,做出了详细的注释。

此算法算是剑指Offer36的升级版,都使用的归并算法,但是此处的算法,难度更高,理解起来更加费劲。

/*
* @Param res 保存逆变对数
* @Param index 保存数组下标索引值,排序数组下标值。
* 此算法使用归并算法,最大差异就在于merge()方法的转变
*
*
*/
public List<Integer> countSmaller(int[] nums) {
int[] res = new int[nums.length];
int[] index = new int[res.length];
for (int i = 0; i < res.length; i++) {
index[i] = i;
}
mergeSort(nums, index, 0, nums.length-1, res);
List<Integer> list = new LinkedList<>();
for (int i : res) {
list.add(i);
}
return list;
} private void mergeSort(int[] nums, int[] index, int l, int r, int[] res) {
if (l >= r) {
return;
}
int mid = (l+r)/2;
mergeSort(nums, index, l, mid, res);
mergeSort(nums, index, mid+1, r, res);
merge(nums, index, l, mid, mid+1, r, res);
}
/*
* 将左右两边排序好的数组进行逆序对计算,分别从左边起始处和右边起始处开始比较,
* 当,左边索引值大于右边时,count++,否则 左边索引值++;
* count值会一直保留,如果右边数组遍历到尾部,左边数组剩下的数的逆序数都会是count;
*
*
*
*/
private void merge(int[] nums, int[] index, int l1, int r1, int l2, int r2, int[] res) {
int start = l1;
int[] tmp = new int[r2-l1+1];
//记录逆序对数
int count = 0;
//temp数组的下标值
int p = 0;
while (l1 <= r1 || l2 <= r2) {
//左边数组遍历结束后,将右边剩余的值放到temp数组中,
if (l1 > r1) {
tmp[p++] = index[l2++];
//右边数组遍历结束后,将左边剩余的值放到temp数组中,
} else if (l2 > r2) {
//l1是原数组索引值,index[l1]是排序好的原数组中索引值。res[index[l1]]对应的原数组索引位置赋逆变数
res[index[l1]] += count;
tmp[p++] = index[l1++];
} else if (nums[index[l1]] > nums[index[l2]]) {
tmp[p++] = index[l2++];
count++;
} else {
//res存放每个数的最大值
res[index[l1]] += count;
tmp[p++] = index[l1++];
}
}
for (int i = 0; i < tmp.length; i++) {
//根据数组值排序,将对应的索引值放到index数组中。
index[start+i] = tmp[i];
}
}
上一篇:【转】所有版本chrome、chromedriver、firefox下载链接


下一篇:C++的ch1&ch2的整理