剑指 Offer 51. 数组中的逆序对

Offer_51

题目描述

方法一:暴力法(双层循环,超时)

package com.walegarrett.offer;

/**
* @Author WaleGarrett
* @Date 2021/2/9 9:12
*/ /**
* 题目详情:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。
* 输入一个数组,求出这个数组中的逆序对的总数。
*/ import java.util.Arrays; /**
* 方法一:暴力解法(超时TLE)
*/
public class Offer_51 {
public int reversePairs(int[] nums) {
int len = nums.length;
int cnt = 0;
for(int i=0; i<len; i++){
int now = nums[i];
for(int j=0;j<i;j++){
if(nums[j] > now)
cnt++;
}
}
return cnt;
}
}

方法二:归并排序法

/**

 * 方法二:归并排序
*/
class Offer_51_2 {
public int reversePairs(int[] nums) {
int len = nums.length;
if(len < 2)
return 0;
int[] second = Arrays.copyOf(nums, len);
return reversePairs(nums, 0, len-1, new int[len]);
}
int reversePairs(int[] nums, int left, int right, int[] tmp){
if(left == right)
return 0;
int mid = (left + right) >> 1;
int leftCnt = reversePairs(nums, left, mid, tmp);
int rightCnt = reversePairs(nums, mid+1, right, tmp);
//左半部分的最大值小于右半部分的最小值,所以这两部分的和没有逆序数对
if(nums[mid] <= nums[mid+1])
return leftCnt + rightCnt;
int crossCnt = mergeAndCount(nums, left, right, tmp);
return leftCnt + rightCnt + crossCnt;
}
//合并并统计逆序数
int mergeAndCount(int[] nums, int left, int right, int[] tmp){
for(int i=left;i<=right;i++){
tmp[i] = nums[i];
}
int mid = (left + right) >> 1;
int cnt = 0;
int i = left;
int j = mid+1;
for(int k=left; k<=right; k++){
if(i == mid+1){
nums[k] = tmp[j];
j++;
}else if(j == right+1){
nums[k] = tmp[i];
i++;
}else if(tmp[i] <= tmp[j]){//左指针右移
nums[k] = tmp[i];
i++;
}else{//右指针右移
nums[k] = tmp[j];
j++;
cnt += (mid-i+1);
}
}
return cnt;
}
}

方法三:树状数组

/**

 * 方法三:树状数组
*/
//树状数组
class BIT{
int[] tree;
int n;
public BIT(int n){
this.n = n;
this.tree = new int[n+1];
} public static int lowbit(int x){
return x&(-x);
}
public void update(int i){
while(i<=n){
++ tree[i];
i += lowbit(i);
}
}
public int query(int i){
int cnt = 0;
while(i!=0){
cnt += tree[i];
i -= lowbit(i);
}
return cnt;
}
}
class Offer_51_3 {
public int reversePairs(int[] nums) {
int len = nums.length;
int[] tmp = new int[len];
tmp = Arrays.copyOf(nums, len);
//离散化:获取元素之间的相对排名
Arrays.sort(tmp);
for(int i=0; i<len; i++){
nums[i] = Arrays.binarySearch(tmp, nums[i]) + 1;
}
BIT bit = new BIT(len);
int ans = 0;
for(int i = len-1; i>=0; i--){
ans+=bit.query(nums[i] - 1);
bit.update(nums[i]);
}
return ans;
}
}

参考题解:数组中的逆序对

最新文章

  1. C语言图形库简单对比及EGE库的安装小手册
  2. Erlang 参考资料
  3. Java抽象类与接口的关系
  4. java进阶书籍推荐
  5. 多线程、多任务管理 简单demo
  6. Oracle表管理
  7. Linux_修改创建文件夹时默认权限(修改为能上传)
  8. Linux下Memcached的安装步骤
  9. Linux常用命令详解(week1_day1_3)--技术流ken
  10. elasticsearch kabana中创建索引
  11. Qt坑点汇总
  12. 容器——list(双向链表)
  13. python下载mp4 同步和异步下载支持断点续下
  14. R 语言 decostand() 函数
  15. java 通用取得 系统硬件信息及 jvm 信息的 jar 包 oshi-core
  16. SNF开发平台WinForm之十五-时间轴控件使用-SNF快速开发平台3.3-Spring.Net.Framework
  17. Go语言基础:method
  18. Python 操作redis 常用方法
  19. testNG 学习笔记 Day2 配置testNG自带的监听器
  20. 启动docker 端口映射时IPV4无法使用

热门文章

  1. Codeforces Round #654 (Div. 2) C. A Cookie for You (思维)
  2. Centos7 搭建Nginx+rtmp+hls直播推流服务器
  3. 2.PowerShell概述
  4. nginx+lua实现灰度发布/waf防火墙
  5. Explain 索引优化分析
  6. 使用SignTool对软件安装包进行数字签名(二)--进行数字签名
  7. Ubuntu16安装Caffe+Python3缺少libboost
  8. window.navigator All In One
  9. CSS font-weight all in one
  10. You Don&#39;t Know the Hack tech in the frontend development