剑指offer面试题14 调整数组顺序使奇数位于偶数前面

解题思路:

1.当遇到让将一个数组、字符串、字符数组划分成两部分的时候,可以考虑使用两个索引,i从数组的前面开始,j从数组的末尾开始,例如快排也是基于这种思想。针对本题,i从左边开始向右寻找到一个偶数,j从右边开始向左寻找到一个奇数,交换这两个索引对应的元素。继续重复上述操作,直到两个索引错开,则表明所有的奇数已经排在偶数的前面了。

2.当题目要求奇数和奇数的相对位置不变,偶数和偶数的相对位置不变时,上面的方法失效。这里有两种思路:(1)基于冒泡排序的思想,一旦遇到相邻两个数前面一个是偶数,后面一个是奇数,就交换。(2)利用空间换时间,额外开辟一个数组,长度和原数组相等,利用原数组统计其中奇数的个数,并在新数组中设置两个索引,一个指向奇数元素的开头,一个指向偶数元素的开头,遍历原数组,如果遇到奇数,则赋给新数组的奇数部分,否则赋给新数组的偶数部分。

/**
 * 调整数组顺序使奇数位于偶数前面
 */
public class Solution {

	/**
	 * 不考虑奇数和奇数间的相对位置,偶数和偶数间的相对位置
	 * 
	 * @param array
	 */
	public void reOrderArray_withoutOrder(int[] array) {

		if (array == null || array.length == 0) {
			return;
		}
		// 因为需要使得奇数位于偶数前面,因此设置两个指针,p1从数组的头开始,专门用于指向偶数
		// p2从数组的尾开始,专门用于指向奇数
		int p1 = 0;
		int p2 = array.length - 1;
		while (p1 < p2) {

			// p1从数组的最左边开始后移,直至找到一个偶数为止
			while (array[p1] % 2 != 0) {
				p1++;
			}
			// p2从数组的最右边开始前移,直至找到一个奇数为止
			while (array[p2] % 2 == 0) {
				p2--;
			}
			if (p1 < p2) {
				// p1不可能等于p2,因为一个指向偶数,一个指向奇数
				swap(array, p1, p2);
				p1++;
				p2--;
			}
		}
		//当p1和p2错开后,表明所有奇数已经在偶数的前面

	}

	private void swap(int[] array, int p1, int p2) {
		
		int temp= array[p1];
		array[p1] = array[p2];
		array[p2] = temp;
	}
	
	public void reOrderArray_RemainOrder(int[] array) {
		//类似于冒泡排序思想
		if(array == null || array.length == 0){
			return;
		}
		
		Bubble_sort(array, array.length);
		
	}
	
	//一趟冒泡
	public void bubble(int[] arr, int n) {
		//一趟排序,将将离数组末尾最近的偶数移动到数组尾部
		for (int i = 0 ; i < n - 1; i++) {
			if (arr[i] %2 == 0 && arr[i+1] % 2 != 0) {
				//如果前面一个是偶数,后面一个是奇数,则交换位置
				swap(arr, i, i+1);
			}
		}
	}
	
	public void Bubble_sort(int[] arr, int n) {
		while (n >= 1) {
			bubble(arr, n);
			n--;
		}
	}
	
	//利用空间换时间
	public void reOrderArray_RemainOrder1(int[] array) {
		
		if(array == null || array.length == 0){
			return;
		}
		
		int length = array.length;
		//开辟一个数组
		int[] temp = new int[length];
		//统计原数组中奇数元素个数
		int numOfOdd = 0;
		for (int i = 0; i < array.length ; i++) {
			if (array[i] % 2 != 0) {
				//证明是奇数
				numOfOdd++;
			}
		}
		
		//在新数组中设置两个指针,一个指向奇数的起始位置,一个指向偶数的起始位置
		//因为奇数在前,i指向奇数的起始位置
		int i = 0;
		int j = numOfOdd;
		//利用原数组给新数组赋值
		for (int k = 0; k < length; k++) {
			if (array[k] % 2 != 0) {
				//如果k指向的是奇数
				temp[i] = array[k];
				i++;
			} else {
				//如果k指向的是偶数
				temp[j] = array[k];
				j++;
			}
		}
		//更新原数组中的值
		for (int p = 0; p < length; p++) {
			array[p] = temp[p];
		}
		 
	}
	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值