调整数组顺序使奇数位于偶数前面(Java)

题目:

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。

第一思路时间复杂度O(n^2):

看到这个题,我的脑海里就浮现了一个时间复杂度为O(n^2)的算法。即从头扫描这个数组,每碰到一个偶数时,拿出这个数字,并把位于这个数字后面的所有数字往前挪动一位。挪完之后在数组的末尾就有一个空位,这时把该偶数放入这个空位,但是要在此位置(刚刚被移走偶数所在的位置)重新判断一次。由于每次碰到一个偶数就需要移动O(n)个数字,因此这个算法的时间复杂度为O(n^2)。

实现代码:

public void reorderOddEven(int []number){
	if(number == null && number.length == 0){
		return;
	}
	int len = number.length; //存储数组长度
	int count = 0; //控制数组遍历的循环次数
	for (int i = 0; i < len && count < len; ++i) { //
		++count;
		int temp = number[i];
		if((temp & 0x1) == 0){ //如果为偶数,移动数组,将数放入数组末尾,并使i在i-1的位置,重新开始判断
			for (int j = i; j < len-1; ++j) {
				number[j] = number[j+1];
			}
			number[len-1] = temp;
			--i;
		}
	}
}

优化代码:

public void reorderOddEven2(int []number){
	if(number == null && number.length == 0){
		return;
	}
	for (int i = 0, j = 0; i < number.length; ++i) {
		if((number[i] & 0x1) != 0){
			int temp = number[i];
			number[i] = number[j];
			number[j] = temp;
			++j;
		}
	}
}

优化思路:

我们可以利用两个指针,来优化这个题的解法。第一个指针p1初始化时指向数组的第一个数字即number[0],它只向后移动;第二个指针初始化时指向数组的最后一个数字即number[number.length-1],它只向前移动。在两个指针相遇之前,第一个指针总是位于第二个指针的前面。如果第一个指针指向的数字是偶数,并且第二个指针指向的数字是奇数,我们就交换这两个数字。

代码实现:

public void reorderOddEven1(int []number){
	int len = number.length;
	if(number == null || len == 0){
		return;
	}
	int begin = 0;
	int end = len -1;
	while(begin < end){
		while((begin < end) && (number[begin] & 0x1) != 0){
			++begin;
		}
		while((begin < end) && (number[end] & 0x1) == 0){
			--end;
		}
		if(begin < end){
			int temp = number[begin];
			number[begin] = number[end];
			number[end] = temp;
		}
	}
}

拓展:

把题目改成把数组中的数按照大小分为两部分,所有的负数都在非负数的前面;

把题目改成把数组中的数按照能不能被3整除分为两部分,所有不能被3整除的数在前面。

上面的两个题目其实它的意图很明显,想让我们把我们上面的函数解耦成两部分:一是判断数字应该在数组前半部分还是后半部分的标准;二是拆分数组的操作。

public boolean isEven(int num){
	if((num & 0x1) == 0){
		return true;
	}else{
		return false;
	}
}
public boolean isDivideBy3(int num){
	if(num % 3 == 0){
		return true;
	}else{
		return false;
	}
}
public boolean isNonnegativeNumber(int num){
	if(num >= 0){
		return true;
	}else{
		return false;
	}
}
public void reorder(int []number){
	int len = number.length;
	if(number == null || len == 0){
		return;
	}
	int begin = 0;
	int end = len -1;
	while(begin < end){
		while((begin < end) && 方法){
			++begin;
		}
		while((begin < end) && 方法){
			--end;
		}
		if(begin < end){
			int temp = number[begin];
			number[begin] = number[end];
			number[end] = temp;
		}
	}
}	

小思:

需要由一道题延伸到一类型题。

猜你喜欢

转载自blog.csdn.net/u013132035/article/details/80580602
今日推荐