寻找数组中的逆序队--2010某谷面试题--在死亡皇后岛挖萝卜的菲尼克斯

题目很简单
比如现在有一组数组
{8,9,4,8,2,3,1}
对于每个数组成员都有一个自己的位置,对于位置靠后然而数字本身小于前方的,都称为逆序数,比如

8/4,8/2,8/3,8/1,9/4,9/3,9/8,9/2,9/1,4/2,4/3,等等等等

题目很简单,在一组数组长度为n的数组中找出所有逆序对

先给出最2的办法
2层循环,遍历数组,靠后并且小于本身,count++
代码要吗?要得点 右上角大叉就出现了
---------------------------------------------我是华丽的分割线--------------------------------------------
在考虑这个问题之前,请先大家了解一下归并排序
比如我现在有个数组{8,9,4,8,2,3,1}
我们可以把数组拆成{8}{9}{4}{8}{2}{3}{1}
先取出第一个数8,此时新数组为{8}
继续到第三个数9 ,发现大于新数组的9,自动插入到后面,{8 9}
继续到第三个数4    发现小于新数组的8,这个时候count出8以及8后方的数字,本例为8 9,所以count+2,并且将4插入新数组的首位 {4 8 9}
继续到第四个数8,发现小于新数组的9,这个时候count出9以及9后方的数字,本例为9,所以count+1,并且将8插入新数组的4与8之间 {4 8 8 9}
继续到第五个数2,发现小于新数组的4,这个时候count出4以及4后方的数字,本例为4 8 8 9,所以count+4,并且将8插入新数组的4与8之间 {2 4 8 8 9}
继续到第六个数3,发现小于新数组的4,这个时候count出4以及4后方的数字,本例为4 8 8 9,所以count+4,并且将8插入新数组的2与4之间 {2 3 4 8 8 9}
继续到第七个数1,发现小于新数组的2,这个时候count出4以及4后方的数字,本例为4 8 8 9,所以count+4,并且将8插入新数组的2与4之间 {1 2 3 4 8 8 9}

好了,这个时候我们不但可以count出所有逆序数,并且排序都完成了,感觉自己棒棒嗒


贴上代码,所有注释部分为英语。。。大家将就看了
package lobs.jibunn.mb.jp.suanfa;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

public class NiXuShu {
	public static void main (String args[]) {

		int countReverse = 0;
		Random rr = new Random();
		int total = 2580;
        
		int orgArray[] = new int[total];
		for (int x =0; x < total -1; x++) {
			orgArray[x] = rr.nextInt(500);
		}
        int newArray[] = new int[total];

		long startTime = System.currentTimeMillis();
		int temp;
		
		for (int i = 0; i < total; i++)  
	    {
	        for (int j = i + 1; j < total; j++)
	        {
	            if (orgArray[i] > orgArray[j])  {
	            	
	            	countReverse++;
	            }
	        }
	    }
//		for (int i = 0; i < total - 1; i++)
//			for (int j = 0; j < total - 1 - i; j++)
//				if (orgArray[j] > orgArray[j + 1]) {
//					temp = orgArray[j];
//					orgArray[j] = orgArray[j + 1];
//					orgArray[j + 1] = temp;
//				}
		
	    
	    long endTime = System.currentTimeMillis();
	    System.out.println("Reverse count is" + countReverse);
		System.out.println("Cost>>>>>>>>>>>>>>>>>>>>>>>>>>>" + (endTime-startTime));
		
//--------------------------------上面是愚蠢的做法捏哈哈哈哈哈哈------------------------------------------------------------------------------------------//	  
	    

		startTime = System.currentTimeMillis();
		//Intialize the first number on the array
		newArray[0] = orgArray[0];
		countReverse = 0;
		//Call the calculate function
		callCalReverse(countReverse,orgArray,newArray,1,1);
		
	        endTime = System.currentTimeMillis();
		System.out.println("Cost>>>>>>>>>>>>>>>>>>>>>>>>>>>" + (endTime-startTime));
	}
	
	private static void callCalReverse(int countReverse, int a[], int b[],int position,int newArraySize) {
		int begin = 0;//calculate the insert position on b
		//In this loop we just do the inserting work.
		while (true) {
			/*Probably that we just need to insert number to last of the array
			 */
			if (a[position] >= b[newArraySize-1]) {
				insertToSortArray(newArraySize,b,a[position],newArraySize);
				break;
			}
		    else if (a[position] <  b[begin]) {
				/* Exp1
				 * a {3,1}
				 * b {2,4}
				 * We need to insert the 3 to group B which between 2 and 4 ,
				 * then count how many numbers in group B is bigger than 3
				 * */
				countReverse = countReverse + newArraySize - begin;
				insertToSortArray(begin,b,a[position],newArraySize);
				break;
			} 
			else {
				begin++;
			}			
           
		}
		if (position < a.length-1) {
			callCalReverse(countReverse,a,b,++position,position);
		} else {
			System.out.println("Reverse count is" + countReverse);
		}
		
	}
    
	/* Insert the number to the array and resort it 
	 * insert 100 to the fifth position
	 * org:    100    1,2,3,4,101
	 * after:*        1,2,3,4,100,101 */
    public static  void insertToSortArray(int begin,int array[],int number, int newArraySize) {
    	int temp = 0;
    	for(int i = begin; i <= newArraySize;i++) {
    		temp = array[i];
    		array[i] = number;
    		number = temp;
    	}
    }
}

思考阶段

本人在初始阶段因为考虑到要反复对于新数组进行插入排序,所以用了linkedlist来操作,但是发现效果非常不好,速度要比最简单的2次遍历都慢,大家可以分析下原因?

然后痛定思痛,决定手写个插入数字到新数组的方法,

速度显著提升
但是后来我把total设为一万后, jvm炸了,google了许多地方,说是因为递归的时候没有考虑function的深度,同学们可以尝试修复这个问题,本人目前能想到的就是把递归改成一个循环,事先count出原数组长度,如果有更好办法的同学请流言,博主还是 很水的,希望能和大家共同进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值