<?php /* - 题目:[BM20 数组中的逆序对](https://www.nowcoder.com/share/jump/4163484761690943983774) - 实现: - 先把数组分隔成子数组 - 先统计出子数组内部的逆序对的数目 - 然后再统计出两个相邻子数组之间的逆序对的数目 - 时间复杂度: O(nlogn) - 空间复杂度: O(n) - 题目要求 - 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P - 题目保证输入的数组中没有的相同的数字 - 要求:空间复杂度 O(n),时间复杂度 O(nlogn)O - 并将P对1000000007取模的结果输出。 即输出P mod 1000000007 - 思路 - 归并排序:分治的思想,这个过程需要使用递归来实现 - 分:数组拆分 - 治:每个小数组如何处理 */ /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param nums int整型一维数组 * @return int整型 */ function InversePairs( $nums ) { $mod = 1000000007; $count = 0; $newNums = mergeSort($nums, $count); return $count % $mod; } function mergeSort($arr, &$count) { // 分:分到元素个数为1 $size = count($arr); if($size <= 1) { return $arr; } // 再次拆分 $mid = $size >> 1; $leftArr = array_slice($arr, 0, $mid); $rightArr= array_slice($arr, $mid); // 继续递归 $left = mergeSort($leftArr,$count); $right = mergeSort($rightArr,$count); // 合并 return merge($left, $right, $count); } // 在合并两个已排序子数组的过程中统计逆序对的数量 function merge($leftArr, $rightArr, &$count) { $result = []; $leftSize = count($leftArr); $rightSize = count($rightArr); $i = 0; $j = 0; // 合并两个数组 while($i < $leftSize && $j < $rightSize) { if($leftArr[$i] <= $rightArr[$j]) { $result[] = $leftArr[$i]; $i++; } else { $result[] = $rightArr[$j]; $j++; // 左边比右边大,答案增加 // 如果是右边的数字更小,那么就是逆序对 $count += count($leftArr) - $i; } } // 剩余的元素 // 左侧的数组 while ($i < $leftSize) { $result[] = $leftArr[$i]; $i++; } // 右侧的数组 while ($j < $rightSize) { $result[] = $rightArr[$j]; $j++; } return $result; } $nums = [1,2,3,4,5,6,7,0]; var_dump(InversePairs($nums)); $nums = [364,637,341,406,747,995,234,971,571,219,993,407,416,366,315,301,601,650,418,355,460,505,360,965,516,648,727,667,465,849,455,181,486,149,588,233,144,174,557,67,746,550,474,162,268,142,463,221,882,576,604,739,288,569,256,936,275,401,497,82,935,983,583,523,697,478,147,795,380,973,958,115,773,870,259,655,446,863,735,784,3,671,433,630,425,930,64,266,235,187,284,665,874,80,45,848,38,811,267,575]; var_dump(InversePairs($nums));