剑指 Offer 51. 数组中的逆序对 + 归并排序 + 树状数组
2024-08-31 02:00:11
剑指 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;
}
}
参考题解:数组中的逆序对
最新文章
- C语言图形库简单对比及EGE库的安装小手册
- Erlang 参考资料
- Java抽象类与接口的关系
- java进阶书籍推荐
- 多线程、多任务管理 简单demo
- Oracle表管理
- Linux_修改创建文件夹时默认权限(修改为能上传)
- Linux下Memcached的安装步骤
- Linux常用命令详解(week1_day1_3)--技术流ken
- elasticsearch kabana中创建索引
- Qt坑点汇总
- 容器——list(双向链表)
- python下载mp4 同步和异步下载支持断点续下
- R 语言 decostand() 函数
- java 通用取得 系统硬件信息及 jvm 信息的 jar 包 oshi-core
- SNF开发平台WinForm之十五-时间轴控件使用-SNF快速开发平台3.3-Spring.Net.Framework
- Go语言基础:method
- Python 操作redis 常用方法
- testNG 学习笔记 Day2 配置testNG自带的监听器
- 启动docker 端口映射时IPV4无法使用
热门文章
- Codeforces Round #654 (Div. 2) C. A Cookie for You (思维)
- Centos7 搭建Nginx+rtmp+hls直播推流服务器
- 2.PowerShell概述
- nginx+lua实现灰度发布/waf防火墙
- Explain 索引优化分析
- 使用SignTool对软件安装包进行数字签名(二)--进行数字签名
- Ubuntu16安装Caffe+Python3缺少libboost
- window.navigator All In One
- CSS font-weight all in one
- You Don&#39;t Know the Hack tech in the frontend development