再说一道面试题及相应的测试[一个有序数组A[n],从中间某一点截断, 把它前半部分接到后半部分的后面形成B[n], 请从B[n]找到A[n]截断位置]



面试题: 一个有序数组A[n],从中间某一点截断, 把它前半部分接到后半部分的后面形成B[n], 请从B[n]找到A[n]截断位置

分析:
  1. 这个数组A必须是有序的, 有序就必须考虑两种情况升序和降序.  假设所有都平序, 应该不满足需要. 比如全为1
  
 
  2. 这个找到截断的位置,应该可以用二分法来做

  3. 数组的个数应该必须大于等于2. 2个数的数组是可以的. 比如3,4.从4处截断可以形成4,3

  
从测试来说, 我们可以考虑以下例子: 

1.  只有1个数的数组

2. 只有2个数的数组

3. 只有一个转折的数组(升序)

4. 只有一个转折的数组(降序)

5. 不止一个转折的数组

6. 全升的数组

7. 全降的数组 
8. 只有一个转折的数组,转折点左右重复数
9. 只有一个转折的数组,非转折点有重复数

如何判断数组A是升序还是降序呢? 其实 只要判断第一个数和最后一个数的大小就可以了.  如果首数大于或等于最后数, 原数组就是升序. 否则降序


不说了,上程序 (C#):

       public static int FindIndexFromArray(int[] bArray)
        {
            //Detect if A[n] is ASC or DSC order
            bool isAscOrder = bArray[0] >= bArray[bArray.Length - 1];

            //Use Binary Search
            int low = 0;
            int high = bArray.Length - 1;
            int mid = -1;
            while (true)
            {
                if ((low + high) / 2 != mid)
                {
                    mid = (low + high) / 2;
                    if (isAscOrder && bArray[low] <= bArray[mid]
                        ||
                        !isAscOrder && bArray[low] >= bArray[mid]
                        )
                    {
                        low = mid;
                    }

                    if (isAscOrder && bArray[mid] <= bArray[high]
                    ||
                    !isAscOrder && bArray[mid] >= bArray[high]
                    )
                    {
                        high = mid;
                    }

                    if (low + 1 == high)
                    {
                        break;
                    }
                }
                else
                {
                    throw new ArgumentException("The provided array did not match the rule. Please check!");
                }
            }

            return bArray.Length - low - 2;
        }


测试程序: 从数组A构造数组B
               public static int[] ConstructArrayB(int[] aArray, int index)
        {
            if (aArray.Length < 2 || index > aArray.Length - 2)
            {
                throw new ArgumentException();
            }

            int[] bArrary = new int[aArray.Length];

            for (int i = 0; i <= index; i++)
            {
                bArrary[i - index + aArray.Length - 1] = aArray[i];
            }

            for (int i = index + 1; i < aArray.Length; i++)
            {
                bArrary[i - index - 1] = aArray[i];
            }

            return bArrary;
        }

        public static void Print(int[] array)
        {
            foreach (int c in array)
            {
                Console.Write(c + " ");
            }
            Console.WriteLine();
        }

        static void Main(string[] args)
        {
            int[] a = { 1, 1, 2, 3, 3, 4,5,12,30 };
            Console.WriteLine("数组A");
            Print(a);
            int index = 2;
            Console.WriteLine("从{0}折断数组A", index);
            int[] b = ConstructArrayB(a, index);
            Console.WriteLine("数组B:");
            Print(b);
            int index2 = FindIndexFromArray(b);
            Console.Write("从数组B得到A的折断点:{0}", index2);
            Console.Write("判断算法正确与否:{0}", index == index2 );
        }


最近 再次想了想, 中间程序 可以简化
        public static int FindIndexFromArray(int[] bArray)
        {
            //Detect if A[n] is ASC or DSC order
            bool isAscOrder = bArray[0] >= bArray[bArray.Length - 1];

            //Use Binary Search
            int low = 0;
            int high = bArray.Length - 1;
            int mid = -1;
            while (low <= high)
            {
                mid = (low + high) / 2;
                if (isAscOrder && bArray[mid] > bArray[mid + 1]
                    ||
                    !isAscOrder && bArray[mid] < bArray[mid + 1]
                    )
                {
                    return bArray.Length - mid - 2;
                }

                if (isAscOrder && bArray[mid] <= bArray[high]
                    ||
                    !isAscOrder && bArray[mid] <= bArray[high]
                 )
                {
                    high = mid;
                }
                else
                {
                    low = mid;
                }
            }

            return bArray.Length - mid - 2;
        }


  
  



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值