数组中的逆序对

[ 编程题 ]- 数组中的逆序对
 
【题目解析】: 数组的逆序对考题较多,比如示例的数组: [1,2,3,4,5,6,7,0] 那么,它包含逆序对有: {1,0},{2,0},
{3,0},{4,0},{5,0},{6,0},{7,0} 总共 7 个逆序对。再比如数组 {7,5,6,4} ,逆序对总共有 5 对, {7,5},{7,6},{7,4},{5,4,{6,4}
 
【解题思路】: 思路 1 :暴力解法,顺序扫描整个数组,每扫描到一个数字的时候,逐个比较该数字和它后面的数
字的大小。如果后面的数字比它小,则这两个数字就组成一个逆序对。假设数组中含有 n 个数字,由于每个数字都
要和 O(n) 个数字作比较,因此这个算法的时间复杂度是 O(n2)
 
思路 2 :分治思想,采用归并排序的思路来处理,如下图,先分后治:先把数组分隔成子数组,先统计出子数组内
部的逆序对的数目,然后再统计出两个相邻子数组之间的逆序对的数目。在统计逆序对的过程中,还需要对数组进
行排序,其实这个排序过程就是归并排序的思路 .
逆序对的总数 = 左边数组中的逆序对的数量 + 右边数组中逆序对的数量 + 左右结合成新的顺序数组时中出现的逆序对
的数量;
 
【示例代码】:
import java.util.*;
public class AntiOrder {
    public int count(int[] A, int n) {
       if (A == null || n == 0) {
            return 0;
         }
            return mergeSortRecursion(A, 0, n - 1);
   }
 
    public static int mergeSortRecursion(int[] arr, int l, int r) {
          if (l == r) {
            return 0;
          }
           int mid = (l + r) / 2;
 //逆序对的总数=左边数组中的逆序对的数量+右边数组中逆序对的数量+左右结合成新的顺序数组时中出现的
逆序对的数量;
          return mergeSortRecursion(arr, l, mid) + mergeSortRecursion(arr, mid + 1, r) +
merge(arr, l, mid, r);
 }
 
    public static int merge(int[] arr, int left, int mid, int right) {
      int[] temp = new int[right - left + 1]; 
      int index = 0;
      int i = left;
      int j = mid + 1;
      int inverseNum = 0;// 新增,用来累加数组逆序对
      while (i <= mid && j <= right) {
          if (arr[i] <= arr[j]) {
            temp[index++] = arr[i++];
          } else {
         // 当前一个数组元素大于后一个数组元素时,累加逆序对
         // s[i] > s[j] 推导出 s[i]...s[mid] > s[j]

           inverseNum += (mid - i + 1);
           temp[index++] = arr[j++];
      }
   }
      while (i <= mid) {
        temp[index++] = arr[i++];
       }
      while (j <= right) {
        temp[index++] = arr[j++];
       }
      for (int k = 0; k < temp.length; k++) {
          arr[left++] = temp[k];
       }
          return inverseNum;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值