剑指offer第二版——面试题51(java)

面试题:数组中的逆序对

题目:

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。

输入一个数组,求出这个数组中的逆序对的总数。

例如,在数组{7,5,6,4}中,一共存在5个逆序对,分别是(7,6),(7,5),(7,4),(6,4)和(5,4)

思路:

如果直接顺序扫描整个数组,则时间复杂度太高,不采用该方法

以{7,5,6,4}为例分析统计逆序对的过程,每扫描到一个数字,不将它与其后面的所有数字进行比较,而是比较相邻的两个数字

每次比较,会生成一个由小到大排好序的数组

如7 5 6 4中,先比较7和5 6和4 ,可知7和5是一对逆序对,6和4也是一对逆序对,对比之后对其分别排序,此时有两个子数组,即57和46,且57在46左边。

对这两个子数组再进行逆序对的计算,从每个数组的末尾开始:

先是7和6,此时7在6左边且7>6,6是46中的最大数,而7>6,说明7大于右边数组的所有数,所以右边数组从头到6有多少个数字,就有多少个逆序对。此时将7排到新数组最大的位置,左边未排序的数字还有5

此时比较的为5和6,因为5<6,所以此处不存在逆序对,直接把6放到新数组的7前面,右边未排序的数字还有4

此时比较的为5和4,因为5>4,此时右边数组从头到4的数字有多少个,就有多少对逆序对。将5放到新数组的6前面

此时只剩4了,直接将4放到新数组中的5的前面

简短思路:

上面所说的就相当于在归并排序中加入了一个count来计算

归并排序时,先两两进行排序,再将排序好的结果合并排序,最后实现对整个数组的排序

其中两两排序就等于上面所说的两两比较之后进行排序,左右两个数组有多个数字时,也只需要利用index来计算开始到当前位置的数字有多少个

因此代码是在归并排序中只加入了一个长度为1的数组来记录count,在每次比较用于排序时,加入了count的计算

public class Q51 {
	public static void main(String[] args) {
		int[] a = new int[] {7,5,6,4};
		int[] s = new int[] {0};
		merge(a,0,a.length-1,s);
		System.out.printf("pairs:%d",s[0]);
	}
	
	
	public static int[] merge(int[] a,int start, int end,int[] s) {
		if(start=0 && j>=0) {
				if(leftarr[i]rightarr[j]){
					s[0] = s[0]+j+1;
					newArr[loc--] = leftarr[i--];
				}
			}
			
			while(i>=0) {
				newArr[loc--] = leftarr[i--];
			}
			
			while(j>=0) {
				newArr[loc--] = rightarr[j--];
				}
			return newArr;
			
			}else {
				return new int[] {a[start]};
			}
	}
}

 

你可能感兴趣的:(剑指offer第二版)