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

题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。(相对位置:两数之间位置,比如:{1,2,3,4,5},偶数间,2的相邻偶数为4,那么调整数组后,2的相邻偶数也必须为4)。
思路:
用两个索引,一个指向数组的第一个数字,把第二个索引指向数组的最后一个数字,然后第一个索引往后移动,直到碰到第一个偶数,第二个索引往前移动,指导碰到第一个奇数,如果第一个索引小于第二个索引,那么就交换两个索引的值,然后重复上述操作,直到第一个索引大于第二个索引,结束操作,此时,数组中所有的奇数都将位于偶数前面。
例如:有一数组{1,2,3,4,5,6,7,8},现第一个索引指向数组中的第一个数1,第二个索引指向数组的最后一个数8,第一个索引开始往后移动,找到第一个偶数,此时,索引指向的值为2。第二个索引开始移动,直到遇到第一个奇数,此时第二个索引指向的值为7,因为此时第一个索引所指值的下标为1,小于第二个索引所指值得下标6,所以交换2和7得位置,此时数组内容为:{1,7,3,1,5,6,2,8}.
按照上述操作,重复直到第一个索引小于第二个索引,结束循环,数组得调整完成。
以下有三种解决该操作的方法。其中第一种和第二种的时间复杂度与空间复杂度皆小于第三种方法,但是由于前两种方法无法解决数字间的相对位置不变,由此需要使用第三种方法来解决相对位置不变的问题。相对于最基本的思想:“从头遍历数组,每遇到一个偶数,就把后面的数往前移,最后空出的位置插入遇到的偶数。”第三种方法有点空间换时间的概念,直接用两个数组来储存奇偶数,然后遍历完数组之后再把偶数数组的值插入奇数数组中,时间复杂度O(N)。

using System;
namespace 调整数组顺序使奇数位于偶数前面
{
    class Program
    {
        static void Main(string[] args)
        {
            //Test1
            Console.Write("Test1");
            int[] arr1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            Console.Write("\nAgo:");
            PrintArray(arr1);
            Console.Write("\nAfter:");
            PrintArray(ReOrderArray3(arr1));
            //Test2
            Console.WriteLine("\nTest2:");
            int[] arr2 = { };
            PrintArray(ReOrderArray1(arr2));
            //Tes3
            Console.WriteLine("\nTest3:");
            Console.WriteLine("Ago:");
            PrintArray(arr1);
            Console.WriteLine("After:");
            int[] arr3 = { 1, 2, 3, 4, 12, 6, 7, 15, 9, 10 };
            PrintArray(ReOrderArray2(arr3));
        }

        /// <summary>
        /// 用于重新排列奇偶数在数组中的顺序,但是该函数无法控制偶数与偶数、奇数与奇数间的相对位置
        /// </summary>
        /// <param name="array">调整的数组</param>
        /// <returns></returns>
        public static int[] ReOrderArray1(int[] array)
        {
            if (array == null || array.Length < 1)
                return array;

            int pre = 0, last = array.Length - 1;
            while (pre < last)
            {
                //从前往后查找,找到最近的一个偶数
                while (pre < last && (array[pre] & 0X1) != 0)
                    pre++;

                //从后往前查找,找到最近的一个奇数
                while (last > pre && (array[last] & 0X1) == 0)
                    last--;

                if (pre < last)
                {
                    int temp = array[pre];
                    array[pre] = array[last];
                    array[last] = temp;
                }
            }

            return array;
        }

        //声明一个指向函数的委托,用于在函数ReOrderArray2中调用委托作为形参使用
        private delegate bool Event(int n);
            /// <summary>
        /// 用于潘昕排列奇偶数在数组中的位置,依然无法控制偶数与偶数、奇数与奇数之间的相对位置。但是相对于ReOrder Array1来说,ReOrder Array2减少了数据间的耦合性,可以把IsEvent作为一个标准,如果排列的条件做了改变,只需要重新编写一个标准(重写IsEvent)即可实现新的功能模块,提高了代码的重用性,为功能扩展提供了便利
        /// </summary>
        /// <param name="array">用于调整的数组</param>
        /// <returns></returns>
        public static int[] ReOrderArray2(int[] array)
        {
            int[] arr= ReOrder(array, IsEvent);
            Console.WriteLine("\n按奇偶数分组排列:");
            PrintArray(arr);
            arr = ReOrder(array, IsEvent2);
            Console.WriteLine("\n按能否整除3的数分组排列:");
            return arr;
        }

        /// <summary>
        /// 此函数是把ReOrderArray1分解成两部分的第一部分,用于判断数字应该在数组前半部分还是后半部分
        /// </summary>
        /// <param name="array">调整的数组</param>
        /// <param name="func">分组的标准,可以重写标准来改变函数的分组</param>
        /// <returns></returns>
        private static int[] ReOrder(int[] array,Event isEvent)
        {
            if (array == null || array.Length < 1)
                return null;

            int pre = 0, last = array.Length - 1;
            while (pre<last)
            {
                //找到最近的一个偶数
                while (pre < last && !isEvent(array[pre]))
                    pre++;
                //找到最近的一个奇数
                while (pre < last && isEvent(array[last]))
                    last--;

                if (pre < last)
                {
                    int temp = array[pre];
                    array[pre] = array[last];
                    array[last] = temp;
                }
            }
            return array;
        }

        /// <summary>
        /// 分组的标准,用于判断传入的数是否为一个偶数,如果是则返回真,否则返回假
        /// </summary>
        /// <param name="n">传入的需要判断的数</param>
        /// <returns></returns>
        private static bool IsEvent(int n)
        {
            return (n & 0x1) == 0;
        }

        /// <summary>
        /// 用于测试的一个新标准,把能整除3的值列为一个新的分组放在数组的后面
        /// </summary>
        /// <param name="n">传入需要判断的数</param>
        /// <returns></returns>
        private static bool IsEvent2(int n)
        {
            return (n % 3) == 0;
        }

        public static int[] ReOrderArray3(int[] array)
        {
            int[] arr = new int[array.Length];
            int[] ouShu = new int[array.Length];
            int ji = 0,ou=0; //奇数的个数,偶数的个数
            for(int i = 0; i < array.Length; i++)
            {
                if ((array[i] & 0X1) != 0)
                {
                    arr[ji++] = array[i];
                }
                else
                    ouShu[ou++] = array[i];
            }

            for(int i = 0; i < ou; i++)
            {
                arr[ji++] = ouShu[i];
            }

            return arr;
        }

        private static void PrintArray(int[] array)
        {
            if (array == null || array.Length < 1)
                return;
            for (int i = 0; i < array.Length; i++)
            {
                if (i % 5 == 0)
                    Console.WriteLine();
                Console.Write(array[i] + "\t");
            }
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值