剑指 Offer 51. 数组中的逆序对 + 归并排序 + 树状数组
剑指 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;
}
}

参考题解:数组中的逆序对
剑指 Offer 51. 数组中的逆序对 + 归并排序 + 树状数组的更多相关文章
- [剑指offer]51-数组中的逆序对(归并排序)
题目链接 https://www.nowcoder.com/questionTerminal/96bd6684e04a44eb80e6a68efc0ec6c5 题意 在数组中的两个数字,如果前面一个数 ...
- AcWing 107. 超快速排序(归并排序 + 逆序对 or 树状数组)
在这个问题中,您必须分析特定的排序算法----超快速排序. 该算法通过交换两个相邻的序列元素来处理n个不同整数的序列,直到序列按升序排序. 对于输入序列9 1 0 5 4,超快速排序生成输出0 1 4 ...
- 力扣Leetcode 面试题51. 数组中的逆序对 - 归并排序
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 示例 1: 输入: [7,5,6,4] 输出: 5 限制: 0 <= ...
- 九度OJ 1348 数组中的逆序对 -- 归并排序
题目地址:http://ac.jobdu.com/problem.php?pid=1348 题目描述: 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求 ...
- 51nod1019逆序数(归并排序/树状数组)
题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1019 题意:中文题诶- 思路: 方法1:归并排序- 归并排序过 ...
- 【BZOJ 3295】动态逆序对 - 分块+树状数组
题目描述 给定一个1~n的序列,然后m次删除元素,每次删除之前询问逆序对的个数. 分析:分块+树状数组 (PS:本题的CDQ分治解法见下一篇) 首先将序列分成T块,每一块开一个树状数组,并且先把最初的 ...
- Bzoj 3295: [Cqoi2011]动态逆序对 分块,树状数组,逆序对
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2886 Solved: 924[Submit][Stat ...
- Day2:T4求逆序对(树状数组+归并排序)
T4: 求逆序对 A[I]为前缀和 推导 (A[J]-A[I])/(J-I)>=M A[j]-A[I]>=M(J-I) A[J]-M*J>=A[I]-M*I 设B[]=A[]-M*( ...
- bzoj3295 [Cqoi2011]动态逆序对 cdq+树状数组
[bzoj3295][Cqoi2011]动态逆序对 2014年6月17日4,7954 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数. ...
随机推荐
- HDU 1565 方格取数 状压dp
题目: 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大. Input 包括多 ...
- hdu4501——小明系列故事——买年货(多维背包)
题解: 思路:将v1,v2,k都当作一种体积,开三维dp数组,每种物品只能取一次 代码中的for循环是倒着进行的,知道01背包和完全背包的肯定明白,倒着进行的就代表每种物品只选择一次 代码: 1 #i ...
- Smith Numbers POJ - 1142 暴力递归枚举
题意: 给你一个数x,把这个分解成素数之积(假设是x1*x2*x3),如果 x的每一数位的和 等于 x1每一数位的和加上x2每一数位的和加上x3每一数位的和,那么他就是题目要找的数 示例: ...
- 洛谷 P1077 摆花 (背包DP)
题意:有\(n\)种花,每种花有\(a_i\)盆,现在要摆\(m\)盆花,花的种类从\([1,n]\)有序排放,问有多少种方案数. 题解:这题可以借用01背包的思路,感觉更好想一点,我们首先枚举\(n ...
- HDU - 1789 dp
题意: 众所周知lyb根本不学习.但是期末到了,平时不写作业的他现在有很多作业要做. CUC的老师很严格,每个老师都会给他一个DDL(deadline). 如果lyb在DDL后交作业,老师就会扣他的分 ...
- Educational Codeforces Round 94 (Rated for Div. 2) C. Binary String Reconstruction (构造)
题意:给你一个字符串\(s\),原字符串为\(w\),如果\(i>x\)且\(w_{i-x}=1\),那么\(s_{i}=1\),如果\(i+x\le n\)且\(w_{i+x}=1\),那么\ ...
- Dapr微服务应用开发系列1:环境配置
题记:上篇Dapr系列文章简要介绍了Dapr,这篇来谈一下开发和运行环境配置 本机开发环境配置 安装Docker 为了方便进行Dapr开发,最好(其实不一定必须)首先在本机(开发机器)上安装Docke ...
- 国产smartbits版本-minismb如何测试路由器III
Minismb测试仪表是复刻smartbits的国产版本,是一款专门用于测试智能路由器,网络交换机的性能和稳定性的软硬件相结合的工具.可以通过此工具测试任何ip网络设备的端口吞吐率,带宽,并发连接数和 ...
- OpenStack Train版-10.安装neutron网络服务(网络节点:可选)
可选:安装neutron网络服务节点(neutron01网络节点192.168.0.30)网络配置按照官网文档的租户自助网络 配置系统参数 echo 'net.ipv4.ip_forward = 1' ...
- Gitlab 快速部署及日常维护 (二)
一.概述 上一篇我们将Gitlab的安装部署和初始化设置部分全部讲解完成了,接下来我们介绍Gitlab在日常工作中常遇见的问题进行梳理说明. 二.Gitlab的安装和维护过程中常见问题 1.Gitla ...