剑指offer数组练习

1.面试题第56题

题目描述

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

1)最初的思路:将数组中的第一个数字与其他的数字进行对比,如果有与它相同的就将第二个数字与其他数字对比,依次下去。问题:会发现时间复杂度过高。真正写代码时会根据题目的特征加一些判断,来减小比较的次数,例如将添加一个计数器,在有两个出现一次数字时就停止遍历数组,但依然不是一个好的方法。

代码实现如下(在牛客网上运行通过):

//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        int count = 0;
        boolean flag = true;
        for(int i=0;i<array.length;i++)
        {
            flag = true;
            for(int j=0;j<i;j++)
            {
                if(array[i]==array[j])
                {
                    flag = false;
                }
            }
            for(int j=i+1;flag==true&&j<array.length;j++)
            {
                if(array[i]==array[j])
                {
                    flag = false;
                }
            }
            if(flag==true)
            {
                count++;
                if(count==1)
                    num1[0] = array[i];
                if(count==2)
                {
                    num2[0] = array[i];
                    break;
                }
            }
        }
    }
}

2)剑指offer作者给出的思路:

2.面试题第21题

题目描述

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

常见思路:从头扫描这个数组,每碰到一个偶数,拿出这个数字,并把位于这个数字后面的所有数字都向前挪动一位,将取出的偶数放到最后,由于每碰到一个偶数就需要移动O(n)个数字,因此总的时间复杂度是O(n^2)

	public static void reOrderArray1(int [] array)
	{
			int i = 0;
			int count = 0;
			//count防止代码继续判断已经被挪过的偶数,进入死循环
			while(i<=array.length-1&&count!=array.length-i-1)
			{
				if(array[i]%2==0)	//如果是偶数
				{
					int temp = array[i];
					for(int k=i;k+1<=array.length-1;k++)
					{
						array[k] = array[k+1];
					}
					array[array.length-1] = temp;
					count++;
				}
				else
				{
					i++;
				}
			}
	}

更好的方法:维护两个指针:第一个指针初始化指向数组的第一个数字,它只向后移动。第二个指针初始化指向数组的最后一个数字,它只向前移动。如果第一个指针指向偶数就停止移动,同样的第二个指针指向奇数就停止移动,然后两只指针指向的数字交换。两指针重复上面的操作,直到第二个指针在第一个指针前面为止。

代码实现:

	public static void reOrderArray2(int [] array)
	{
		int i = 0;
		int j = array.length - 1;
		while(i<j)
		{
			while(i<j&&array[i]%2==1)
			{
				i++;
			}
			while(i<j&&array[j]%2==0)
			{
				j--;
			}
			if(i>=j)			//这一行代码是重点,类似与快速排序
				break;
			int temp = array[i];
			array[i] = array[j];
			array[j] = temp;
		}
	}

题目描述

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并 保证奇数和奇数,偶数和偶数之间的相对位置不变

思路:用两个指针考,指针i指向第一个偶数,指针j指向第一个奇数,将[i,j-1]的数都向右移动一位,将指针j指向的数据赋值给指针i指向的位置。

代码实现:

public class Solution {
    public static void reOrderArray(int [] array) {
    	int i = 0;
    	int j = i+1;
    
    	while(i<=array.length-1&&j<=array.length-1)
    	{
    		while(i<=array.length-1&&array[i]%2==1)
        	{
        		i++;
        	}
    		j = i+1;
        	while(j<=array.length-1&&array[j]%2==0)
        	{
        		j++;
        	}
        	if(j<=array.length-1)
        	{
        		int temp = array[j];
	        	for(int k=j;k-1>=i;k--)
	        	{
	        		array[k] = array[k-1];
	        	}
	        	array[i] = temp;
        	}
        	if(j>array.length-1)    //如果发现后面的都是偶数了就退出循环
        		break;
        	i++;
    	}
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值