【剑指Offer】- 数组中的逆序对
题目链接:剑指Offer51
题目描述:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
限制:
0 <= 数组长度 <= 50000
题解:
解题思路:
在排序过程中统计逆序对的数量。
归并排序:
1.递归划分。计算数组的中点middle,递归划分左数组:left = nums.slice(0, middle),递归划分右数组:right = nums.slice( middle)。递归终止条件:当数组长度为1时,终止递归。
2.合并。创建辅助数组res,设置指针cur,i,j分别指向res,左,右数组。
1)当res>left.len,左子数组已合并完,只需添加right到res中;
2)当res > right.len, 右子数组已合并完,只需添加left到res中;
3)左右数组均未合并完,比较左右数组值的大小,若左子数组<右子数组,不存在逆序,合并数组;若左子数组 > 右子数组,则存在逆序。由于子数组已有序,所以当前left[i]之后的值均 > right[j],所以逆序长度为left.len - i。
/**
* @param {number[]} nums
* @return {number}
*/
var reversePairs = function(nums) {
let sum = 0;
mergeSort(nums);
//归并排序
function mergeSort(nums){
if(nums.length <= 1)
return nums;
let middle = Math.floor(nums.length / 2);
let left = nums.slice(0, middle);
let right = nums.slice(middle, nums.length);
return merge(mergeSort(left), mergeSort(right));
}
//两两合并
function merge(left, right){
let len = left.length + right.length;
let res = new Array(len).fill(0);
for(let cur = 0, i = 0, j = 0; cur < len; cur++)
{
if(i >= left.length)
res[cur] = right[j++];
else if(j >= right.length)
res[cur] = left[i++];
else if(left[i] <= right[j])
res[cur] = left[i++];
else
{
res[cur] = right[j++];
// left[i] > right[j]的情况, 即left[i, end)和right[j]都是逆序对
sum += left.length - i;
}
}
return res;
}
return sum;
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~