剑指offer51(Java)-数组中的逆序对(困难)
题目:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例1:
输入: [7,5,6,4]
输出: 5
限制:
0 <= 数组长度 <= 50000
解题思路:
这道题的核心在于 归并排序,在归并排序的基础上进行求解 逆序对。
题解参考 K神老师的题解和 liweiwei1419老师的讲解视频,这道题对于我来说有点困难~
归并排序的核心在于分治思想:
- 分: 不断将数组从中点位置划分开(即二分法),将整个数组的排序问题转化为子数组的排序问题;
- 治: 划分到子数组长度为 1 时,开始向上合并,不断将 较短排序数组 合并为 较长排序数组,直至合并至原数组时完成排序。

大致思想:
主函数reversePairs():
1.执行差分数组方法mergeSort()
2.返回逆序对总数
差分数组mergeSort():
1.将数组一份为二,进行递归拆分;
2.执行归并排序merge(),并统计逆序对的个数。
归并排序merge():
1.定义一个临时数组,用于统计合并过程中的临时数组;
2.设置双指针 i 和 j 分别指向左右子数组的首元素即 i = left , j = mid+1,设置t=0指向临时数组下标:
- nums[i] <= nums[j]:说明左子数组的元素小于右子数组,此时不存在逆序对,直接将nums[i]放入temps[t],执行 i++,j++;(类似于下图情况)

- 否则 nums[i] > nums[j]:说明左子数组及左子数组剩下的元素都大于右子数组元素,则将小的nums[j]放入temps[t],并执行j++,t++,逆序数对数加 m-i+1个(类似于下图情况)

- 当 i <= mid 时(j > right),代表右子数组已经合并完,剩余的左子数组加入到temp后面即可;
- 当 j <= right 时(i>mid),代表左子数组已经合并完,剩余的右子数组加入到temp后面即可。

- 最后需要将每一轮排好序的数组放回原数组。
疑惑:nums[left + k] = temp[k]:因为合并方法merge()中的left根据每一次递归都不一样的,故每一次排好序的数都应该从left开始放。

代码:
1 class Solution {
2 //定义一个全局变量用于计算逆序对的个数
3 int count = 0;
4 public int reversePairs(int[] nums) {
5 mergeSort(nums, 0, nums.length-1);
6 return count;
7 }
8 //将数组拆分
9 public void mergeSort(int[] nums,int left,int right){
10 //如果只有一个或空则直接退出
11 if (left >= right) return;
12 int mid = (left + right) /2;
13 //对左边进行拆分
14 mergeSort(nums, left, mid);
15 //对右边进行拆分
16 mergeSort(nums, mid+1, right);
17 //合并
18 merge(nums,left,right,mid);
19 }
20 //合并方法
21 public void merge(int[] nums,int left,int right,int mid){
22 //定义一个临时数组
23 int[] temp = new int[right-left+1];
24 //定义指针指向第一个数组的第一个元素
25 int i = left;
26 //定义指针指向第二个数组的第一个元素
27 int j = mid+1;
28 //定义一个指针指向临时数组的第一个元素
29 int t = 0;
30 //当两数组都有数据的时候进行遍历
31 while (i <= mid && j <= right){
32 //如果第一个数组元素小,那么就直接将小的放入临时数组
33 if(nums[i] <= nums[j]){
34 temp[t++] = nums[i++];
35 }else{
36 //如果第一个数组元素大,那么就要将小的先放,并统计逆序对的个数
37 count += mid-i+1;
38 temp[t++] = nums[j++];
39 }
40 }
41 //当右边的数组已经遍历完,左边还剩余的时候,直接将剩余元素加入临时数组
42 while (i <= mid){
43 temp[t++] = nums[i++];
44 }
45 //当左边的数组已经遍历完,右边还剩余的时候,直接将剩余元素加入临时数组
46 while (j <= right){
47 temp[t++] = nums[j++];
48 }
49 //用临时数组的值去覆盖原数组的值
50 for(int k = 0; k < temp.length; k++){
51 nums[left + k] = temp[k];
52 }
53 }
54 }
剑指offer51(Java)-数组中的逆序对(困难)的更多相关文章
- 剑指 Offer 51. 数组中的逆序对 + 归并排序 + 树状数组
剑指 Offer 51. 数组中的逆序对 Offer_51 题目描述 方法一:暴力法(双层循环,超时) package com.walegarrett.offer; /** * @Author Wal ...
- 【Java】 剑指offer(51)数组中的逆序对
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成 ...
- 【剑指offer】数组中的逆序对
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/mmc_maodun/article/details/27520535 转载请注明出处:http:// ...
- 剑指offer-36:数组中的逆序对
参考:1. https://www.geeksforgeeks.org/merge-sort/ 2.<剑指Offer:名企面试官精讲典型编程题> 题目描述 在数组中的两个数字,如果前面一个 ...
- Go语言实现:【剑指offer】数组中的逆序对
该题目来源于牛客网<剑指offer>专题. 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对10000 ...
- 剑指Offer 35. 数组中的逆序对 (数组)
题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...
- 【剑指offer】数组中的逆序对。C++实现
原创文章,转载请注明出处! 博客文章索引地址 博客文章中代码的github地址 # 题目 # 思路 基于归并排序的思想统计逆序对:先把数组分割成子数组,再子数组合并的过程中统计逆序对的数目.统计逆序对 ...
- [剑指Offer] 35.数组中的逆序对
题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...
- 剑指offer:数组中的逆序对
题目描述: 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%100 ...
- 剑指offer35:数组中的逆序对
1 题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%10 ...
随机推荐
- obs 屏幕录像 1. 屏幕放大缩小 2. 圆形摄像头
obs 屏幕录像 1. 屏幕放大缩小 2. 圆形摄像头 屏幕放大缩小 windows 放大镜 屏幕放大快捷键 win + '+' 是放大屏幕 win + '-' 是缩小屏幕 因为obs不支持缩放功能, ...
- JDK1.8版本java字符串常量池里存的是String对象还是引用?
转载自http://t.csdn.cn/iD9LD 先下结论:对象! 众所周知,JDK1.8版本中,String常量池已经从方法区中的运行时常量池分离到堆中了,那么在堆中的String常量池里存的是S ...
- linux下几种快速清空文件内容的方法
[root@iamzken ~] : > filename [root@iamzken ~] > filename [root@iamzken ~] echo "" & ...
- 什么是XR扩展现实,XR云串流平台有哪些
什么是云XR (AR/VR/MR/SR) 虚拟现实(VR),传统的实现方式是通过计算机模拟虚拟环境,从而给人一种环境沉浸感.与传统视频相比,VR带来了前所未有的沉浸式体验. 增强现实(AR)是一种无缝 ...
- django(视图层)
更详细的视图层讲解,看下面链接 https://www.cnblogs.com/xiaoyuanqujing/articles/11643459.html 一. 三板斧 ''' HttpRespons ...
- View之Canvas,Paint,Matrix,RectF等介绍
目录介绍 1.Paint画笔介绍 1.1 图形绘制 1.2 文本绘制 2.Canvas画布介绍 2.1 设置属性 2.2 画图[重点] 2.3 Canvas对象的获取方式 2.4 Canvas的作用 ...
- http内网穿透CYarp[开源]
0 前言 在物联网领域中,mqtt消息一直是海量设备连接到平台的标配协议,而平台向移动端开放的操作接口往往是http协议,这就要求平台为两种协议作消息一一适配.在某些情况下,这些设备是有操作系统的li ...
- 三维模型3DTile格式轻量化压缩必要性分析
三维模型3DTile格式轻量化压缩必要性分析 理解3DTile格式轻量化压缩的必要性,首先需要理解三维模型的复杂性和数据量.三维模型通常包含大量的顶点.面片和纹理信息,这使得其数据量非常大,尤其对于大 ...
- 超高并发下,Redis热点数据风险破解
★ Redis24篇集合 1 介绍 作者是互联网一线研发负责人,所在业务也是业内核心流量来源,经常参与 业务预定.积分竞拍.商品秒杀等工作. 近期参与多场新员工的面试工作,经常就 『超高并发场景下热点 ...
- 记录--iview 使用爬坑
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前段时间公司需要开发一个后台管理系统,时间比较急迫,一两天时间.想一想自己一点一点的搭建起来可能性不太大,就想着有没有现成的可以改一改,就 ...