码迷,mamicode.com
首页 > 编程语言 > 详细

混乱无序的整数数组如何实现左侧全是奇数右侧全是偶数(数字不要求排序)

时间:2015-08-25 23:48:38      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:c#   面试   算法   

今天同事估计闲得蛋疼,突然开始回忆以前面试过程中被面到过的一些面试问题,有逻辑的,有算法的,然后来考我思路,标题对应的算法就是他碰到的面试算法题之一。

拿到题目的第一个感觉,就是Linq,被Linq带坏了,这种考算法的题目直接来Linq你都逗谁呢,整理一下思路,恩,题目只要求左侧奇数,右侧偶数,并未要求两侧的整数还要分别排序,那算法思路就这么定下来了,按索引从低向高循环,如果遇到偶数,则在循环内进行反向循环,即从高位向低位循环找奇数来实现两者位置交替,算法实现如下:

static void SetLeftSingleAndRightDoubleOne(int[] arr)
{
    int num = 0;
    var prevIndex = arr.Length - 1;
    for (var i = 0; i <= prevIndex; i++)
    {
        if (arr[i] % 2 == 0)
        {//偶数 
            for (var j = prevIndex; j > i; j--)
            {
                num++;
                if (arr[j] % 2 != 0)
                {
                    //奇数
                    var b = arr[i];
                    prevIndex = j - 1;//当前位置已与偶数更换过位置,所以设置值的索引可以减一
                    arr[i] = arr[j];
                    arr[j] = b;
                    break;
                }
            }
        }
        else
        {
            num++;
            //奇数
            continue;
        }
    }
    //Console.WriteLine("ONE RUN NUMS:" + num);
}
咋看算法没问题,时间复杂度应当为f(n)=n-1,但实际一运行,却发现偶尔会出现循环次数高于数组长度的现象,这是为什么呢?因为问题出在反向循环上,如果反向循环到i为止,都未能找到奇数,那也就不会有prevIndex的赋值,那外层的循环也就会继续下去,然后就会出现循环次数高于数组长度的情况,修正代码,增加判断停止标志位:
static void SetLeftSingleAndRightDoubleOne(int[] arr)
{
    int num = 0;
    var prevIndex = arr.Length - 1;
    for (var i = 0; i <= prevIndex; i++)
    {
        if (arr[i] % 2 == 0)
        {//偶数 
            bool stop = false;//停止标志位
            for (var j = prevIndex; j > i; j--)
            {
                num++;
                if (arr[j] % 2 != 0)
                {
                    //奇数
                    var b = arr[i];
                    prevIndex = j - 1;//当前位置已与偶数更换过位置,所以设置值的索引可以减一
                    arr[i] = arr[j];
                    arr[j] = b;
                    break;
                }
                stop = j == i + 1;//多了一步赋值
            }
            if (stop)//虽然多了一步判断,但循环次数有减少
            {//因为反向遍历已经遍历到了i的前一位,所以可以停止遍历了
                break;
            }
        }
        else
        {
            num++;
            //奇数
            continue;
        }
    }
    //Console.WriteLine("ONE RUN NUMS:" + num);
}
OK,算法已经实现,然后得到同事的实现,大体思路一致,都是左右遍历交替,具体如下:
static void SetLeftSingleAndRightDoubleTwo(int[] arr)
{
    int left = 0;
    int right = arr.Length - 1;
    int num = 0;
    while (left < right)
    {
        num++;
        bool leftDouble = arr[left] % 2 == 0;//判断左侧是否是偶数
        bool rightSingle = arr[right] % 2 != 0;//判断右侧是不是奇数
        if (!leftDouble)
        {
            left++;
        }
        if (!rightSingle)
        {
            right--;
        }
        if (leftDouble && rightSingle)
        {
            int t = arr[left];
            arr[left] = arr[right];
            arr[right] = t;
            left++;
            right--;
        }
    }
    //Console.WriteLine("TWO RUN NUMS:" + num);
}
与实现一相比,每次循环都会低位高位找两个位置,并判断是否能进行替换,因为每次循环都判断高低两个位置,所以时间复杂度上要低于实现一

最后就是具体的测试代码,为测试结果更为精准,每个实现都执行10次

Stopwatch watch= new Stopwatch();
for (var i = 0; i < 10; i++)
{
    Console.WriteLine("*******************************");
    Console.WriteLine("Run the " + (i + 1) + "st time");
    var tmp = Enumerable.Range(1, 50/*00000*/).OrderBy(_ => Guid.NewGuid()).Skip(30).ToArray();
    //arr = Enumerable.Repeat<int>(1, 50).ToArray();
    //arr = new int[50];
    var arr1 = tmp.ToArray();
    var arr2 = tmp.ToArray();

    watch.Reset();
    watch.Start();
    SetLeftSingleAndRightDoubleOne(arr1);
    watch.Stop();
    Console.WriteLine("ONE MS:" + watch.ElapsedMilliseconds);
    //Console.WriteLine(string.Join(",", arr1));

    watch.Reset();
    watch.Start();
    SetLeftSingleAndRightDoubleTwo(arr2);
    watch.Stop();
    Console.WriteLine("TWO MS:" + watch.ElapsedMilliseconds);
    //Console.WriteLine(string.Join(",", arr2));
}
最后分别按正确性和执行时间截了两张图,正确性方面两者一致,执行时间方面实现二要略优于实现一

技术分享正确性截图

技术分享执行时间截图

版权声明:本文为博主原创文章,未经博主允许不得转载。

混乱无序的整数数组如何实现左侧全是奇数右侧全是偶数(数字不要求排序)

标签:c#   面试   算法   

原文地址:http://blog.csdn.net/starfd/article/details/47979855

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!