算法--数组

1.长度为n的数组,元素大小为0-n-1,有些数字重复,找出任意一个重复数字。例如{2, 3,  1,0, 2, 5, 3} 对应输出2或3.

        由于数字长度为n,数字大小为0到n-1,可以将数字i放置在数组中i位置,若数组中i位置上数字已经是i,则说明i数字重复了,否则则进行交换,将数字i放置在数组中i位置。

public static int findNum(int[] arr){
		//遍历一遍将arr[i]放在索引为arr[i]位置上,当相等时说明数字重复,不相等则进行交换。
		for(int i=0; i<arr.length; i++){
			if(arr[i]==arr[arr[i]]){
				return arr[i];
			}else{
				int m = arr[arr[i]];
				arr[arr[i]] = arr[i];
				arr[i] = m;
			}
		}
		return -1;
	}

2.不修改数组找出重复的数字,长度为n+1,数字范围在1-n之间,找出数组中重复的任意数字,不能修改数组。

1-n范围内数字有n+1个,说明某个数字重复了。取1-n的中间值m,分为1--m和m+1--n,统计数组中在1--m中元素个数,若大于m,则说明该数字在1--m中,否则在m+1--n中。类似于二分查找,终止条件是,lo==hi并且在这个区间里面的数字个数大于1,说明找到了重复值。

public static int findNum2(int[] arr){
		int lo = 1;
		int hi = arr.length-1;
		while(lo <= hi){
			int mid = (lo + hi) >> 1;
		    int leftNum = count(arr, lo, mid);
		    System.out.println("lo = " + lo + " mid = " + mid + " left num = " + leftNum);
		    if(lo == hi){
		    	if(leftNum > 1) return lo;
		    	else break;
		    }
		    if(leftNum > mid-lo+1)
		    	hi = mid;
		    else
		    	lo = mid + 1;
		}
		return -1;
	}
	
	public static int count(int[] arr, int lo, int hi){
		int num = 0;
		for(int i=0; i<arr.length; i++){
			if(arr[i]>=lo && arr[i]<=hi)
				num++;
		}
		return num;
	}

猜你喜欢

转载自blog.csdn.net/u014106644/article/details/83539282