面经:Count Inversion in an Array

本文介绍了一种高效的逆序对计数算法,利用归并排序的思想,在排序的同时计算出数组中逆序对的数量。这种方法避免了传统双层循环带来的高时间复杂度问题,将复杂度降低至O(n log n)。

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

Topic:面试整理

题目:

Inversion Count for an array indicates – how far (or close) the array is from being sorted. If array is already sorted then inversion count is 0. If array is sorted in reverse order that inversion count is the maximum. 
Formally speaking, two elements a[i] and a[j] form an inversion if a[i] > a[j] and i < j

Example:
The sequence 2, 4, 1, 3, 5 has three inversions (2, 1), (4, 1), (4, 3).



方法:

简单算法:两个循环,第二个指针从第一个指针的后面一个元素开始,比较大小,前面的大,结果加一,复杂度为O(n^2);

利用mergeSort的算法:merge过程中我们会判断前半部分和后半部分的元素大小,如果前半部分的元素大于后半部分,那么从当前这个前半部分的元素到中间元素的所有元素都满足inversion,因此结果加(mid+1-i),把结果融入递归,可解。

参考:

http://www.geeksforgeeks.org/counting-inversions/


Code:

import java.util.*;

class Test{
    public static void main(String[] args){	
		Sort s = new Sort();
		int[] a = {1, 2, 3, 4, 5, 6, 7};
		int[] b = {2, 4, 1, 3, 5};
		
		int[] aux = new int[a.length];	
		
		s.shuffle(a);
		s.display(a);
		System.out.println(s.mergeSort(a, aux, 0, a.length-1));
		// System.out.println(s.mergeSort(b, aux, 0, b.length-1));
		s.display(a);
	}
}

class Sort{
	public int mergeSort(int[] a, int[] aux, int head, int tail){
		if(head == tail)
			return 0;
		int res = 0;
		int mid = (head+tail)/2;
		res += mergeSort(a, aux, head, mid);
		res += mergeSort(a, aux, mid+1, tail);
		res += merge(a, aux, head, mid, tail);
		return res;
	}
	private int merge(int[] a, int[] aux, int head, int mid, int tail){
		int res = 0, cnt = 0, i = head, j = mid+1;
		while(i<=mid && j<=tail){
			if(a[i] < a[j]) aux[cnt++] = a[i++];
			else{
				aux[cnt++] = a[j++];
				res += mid + 1 - i;
			}
		}
		while(i <= mid) aux[cnt++] = a[i++];
		while(j <= tail) aux[cnt++] = a[j++];
		for(int k=0; k<cnt; k++) a[k+head] = aux[k];
		return res;
	}
	
	public void display(int[] a){
		for(int i=0; i<a.length; i++)
			System.out.print(a[i] + " ");
		System.out.println();
		System.out.println("-----------------------------------------------");
	}
	public void shuffle(int[] a){
		Random rnd = new Random();
		for(int i=0; i<a.length; i++)
			swap(a, i, rnd.nextInt(a.length));
	}
	public void swap(int[] a, int i, int j){
		int tmp = a[i];
		a[i] = a[j];
		a[j] = tmp;
	}
	
	
}

小结:

方法二可以看做递归算法的巧妙运用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值