【笔试】48、数组中的逆序对

本文介绍了一种使用归并排序思想来统计数组中逆序对总数的方法。通过递归将数组拆分成更小的部分,并利用辅助数组进行合并,有效地统计出逆序对的数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

核心是递归,但是这个题里面还有一个亮点,就是把原来的被合并数组作为新的合并数组放进去,因为上一层递归的时候那个辅助数组是已经归并排好序了的,我们只要在上面的左右排好序的基础上,进行比较,和排序就可以了


算法的思想,这个题其实就是归并排序的一个变化


/****************************************************************************************
 *题目:数组中的逆序对
 *		在数组中的两个数字如果前面一个数字大于后面的数字,则这个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数
 *时间:2015年10月3日10:17:32
 *文件:InversePairs.java
 *作者:cutter_point
 ****************************************************************************************/
package bishi.Offer50.y2015.m10.d03;

import org.junit.Test;

public class InversePairs
{
	//输入一个数组进行统计
	public int inversePairs(int data[])
	{
		if(data == null)
			return 0;
		//创建一个copy数组
		int copy[] = new int[data.length];
		copy = data.clone();	//这个类似吧data中的值复制一份到copy中,这时候copy中的值和data无关
		
		int count = inversePairsCore(data, copy, 0, data.length - 1);
		
		return count;
	}
	
	//这个题的核心其实就是归并排序
	private int inversePairsCore(int data[], int copy[], int start, int end)
	{
		//当归并到最后单个元素的时候
		if(start == end)
		{
			copy[start] = data[start];	//个人觉得这一步没什么用
			return 0;	//只剩一个元素的集合,是没有逆序对的
		}//if
		
		//归并就是把数组一分为二,那么每段的长度就是
		int length = (end - start) / 2;
		//左边和右边进行递归分解,这里是吧data做copy,copy做data,我觉得在函数里面建立辅助数组结果是一样的
		//但是这里这样做可以节省空间,因为一篇空间得到了重复利用,虽然没什么用
		int left = inversePairsCore(copy, data, start, start + length);	//这个是左边的逆序对的个数
		int right = inversePairsCore(copy, data, start + length + 1, end);	//右边数组的逆序对的个数
		
		//接下来我们对这个数组中的你需对进行统计,我们设定3个游标
		int i = start + length, j = end, indexCopy = end;
		//设定一个参数用来统计逆序对的个数
		int count = 0;
		
		//这个里面对数据进行遍历统计
		while(i >= start && j >= start + length + 1)
		{
			//进行判断,前面的数组中的数据是否比后面的数组中的数大
			if(data[i] > data[j])
			{
				//这里的操作要求data排好序,那么这里的copy数组还是有必要进行传参的
				copy[indexCopy--] = data[i--];
				count += j - start - length;
				//输出逆序对
				for(int k = j; k >= start + length + 1; --k)
				{
					System.out.print("{" + data[i + 1] + "<==>" + data[k] + "}\t");
				}//for
			}//if
			else
			{
				//如果左边比右边小点话,那么直接加入到辅助数组中
				copy[indexCopy--] = data[j--];
			}//else
		}//while
		
		//把剩下的元素都放到辅助数组中
		for(; i >= start; --i)
		{
			copy[indexCopy--] = data[i];
		}//for
		for(; j >= start + length + 1; --j)
		{
			copy[indexCopy--] = data[j];
		}//for
		
		//返回逆序对个数
		return left + right + count;
	}
	
	@Test
	public void test()
	{
		int a[] = {1,2,3,4,5,6};
		int b[] = a.clone();
		a[1] = 10;
		for(int i = 0; i < a.length; ++i)
		{
			System.out.println(b[i]);
		}
		System.out.println("逆序对有:");
		InversePairs ip = new InversePairs();
		int data[] = {7,5,6,4};
		System.out.println("\n" + ip.inversePairs(data));
	}

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值