这是我参与更文挑战的第8天,活动详情查看:更文挑战
计算右侧小于当前元素的个数
给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。
思路分析
套路依旧是先暴力再根据特性剪枝,暴力做法就是两个for循环,j = i + 1 j <= size即可。
我们仔细看看题,emmm不就是逆序对么
不过和逆序对不同的是,逆序对只是统计一个总数,但是这个需要统计每个元素右侧小于当前元素的个数。
相当于我们要设置一个表,map[val]idx,用这种方式记录每个元素右侧小于当前元素的个数。
真的可以用归并排序计算逆序对吗?
在上篇文章中,我简单介绍了一次归并所省略的计算的正确性,我们可以通过利用局部的有序性,来避免暴力的n方复杂度。
但是对于经过归并后,计算的逆序对数量是否正确这部分却证明的不是很详实。
接下来以[10,7,5,2,4,3,6,8]
归并第一次 [10,7] [5,2] [4,3] [6,8]
计算的逆序对有: [10,7] [5,2] [4,3] [6,8]
归并第二次: [7,10,2,5] [3,4,6,8]
计算逆序对有:[2,7] [2, 10] [5,7] [5,10]
归并两次以后我们就可以发现逆序对的获取逻辑
归并出现arr[m] < arr1[x]的时候,一定代表着他们本身这一个逆序对,而同时也代表着arr[m] 与arr1[x..size]的逆序对。
但此时arr.size是极小的(比如说2,或者4)。但是由于arr和arr1再怎么改变位置,都不会影响arr2...size/2的归并。因此在任意时刻他们的局部一定是有序的。
我们把目光聚焦到最后一个arr,比如说,[6,8], [3,4,6,8] 每一次归并一定会新增一部分值和8进行比较,比如说第一次的6,第二次的3,4(当然3,4并不能增加逆序对),第三次的7,10,2,5.
因此一个数字是可以理解为与所有其他前面的数字都进行比较过的。