zoukankan      html  css  js  c++  java
  • 百度面试题:求绝对值最小的数

    参考了这篇博客的内容和思路:http://www.cnblogs.com/nokiaguy/archive/2013/01/29/2881476.html

    有一个已经排序的数组(升序),数组中可能有正数、负数或0,求数组中元素的绝对值最小的数,要求,不能用顺序比较的方法(复杂度需要小于O(n)),可以使用任何语言实现

    例如,数组{-20,-13,-4, 6, 77,200} ,绝对值最小的是-4。

    算法实现的基本思路

    三种情况:
    全负数 全正数 正负皆有
    1:取最右 时间复杂度为o(1)
    2:取最左 时间复杂度为o(1)
    3:二分查找0, 找到为最小,否则最后查找区间,左右取绝对值最小,时间复杂度为o(log2 n)

         解法一:

    View Code
     1      private static IEnumerable<int> GetABSMinValue1(IList<int> arr)
     2         {
     3             var ret = new List<int>();
     4             if (arr.Count < 2)
     5             {
     6                 ret.Add(arr[0]);
     7             }
     8             else
     9             {
    10                 if (arr[arr.Count - 1] <= 0)
    11                 {
    12                     ret.Add(arr[arr.Count - 1]);
    13                 }
    14                 else if (arr[0] >= 0)
    15                 {
    16                     ret.Add(arr[0]);
    17                 }
    18                 else
    19                 {
    20                     //方法一:循环遍历法
    21                     for (int i = 0; i < arr.Count; i++)
    22                     {
    23                         if (arr[i] < 0 && arr[i + 1] >= 0)
    24                         {
    25                             if (Math.Abs(arr[i]) > Math.Abs(arr[i + 1]))
    26                             {
    27                                 ret.Add(arr[i + 1]);
    28                             }
    29                             else if (Math.Abs(arr[i]) < Math.Abs(arr[i + 1]))
    30                             {
    31                                 ret.Add(arr[i]);
    32                             }
    33                             else
    34                             {
    35                                 ret.Add(arr[i]);
    36                                 ret.Add(arr[i + 1]);
    37                             }
    38                         }
    39                     }
    40                 }
    41             }
    42 
    43             return ret;
    44         }

      解法二:

    View Code
     1         private static IEnumerable<int> GetABSMinValue2(IList<int> arr)
     2         {
     3             var ret = new List<int>();
     4             if (arr.Count < 2)
     5             {
     6                 ret.Add(arr[0]);
     7             }
     8             else
     9             {
    10                 if (arr[arr.Count - 1] <= 0)
    11                 {
    12                     ret.Add(arr[arr.Count - 1]);
    13                 }
    14                 else if (arr[0] >= 0)
    15                 {
    16                     ret.Add(arr[0]);
    17                 }
    18                 else
    19                 {
    20                     //方法二:第一步是二分法,第二步循环遍历法
    21                     int low = 0, high = arr.Count - 1, mid;
    22                     while (low <= high)
    23                     {
    24                         mid = (low + high) / 2;
    25                         if (arr[mid] == 0)
    26                             ret.Add(arr[mid]);
    27                         if (arr[mid] > 0) //中间位置为正数
    28                         {
    29                             if (arr[mid - 1] < 0) //中间位置前一个为负数
    30                             {
    31                                 if (Math.Abs(arr[mid - 1]) == arr[mid])
    32                                 {
    33                                     ret.Add(arr[mid - 1]);
    34                                     ret.Add(arr[mid]);
    35                                 }
    36                                 else
    37                                 {
    38                                     ret.Add(Math.Abs(arr[mid - 1]) > arr[mid] ? arr[mid] : arr[mid - 1]);
    39                                 }
    40                                 break;
    41                             }
    42                             high = mid - 1;
    43                         }
    44                         else //中间位置为负数
    45                         {
    46                             if (arr[mid + 1] > 0) //中间位置后一个为正数
    47                             {
    48                                 if (Math.Abs(arr[mid]) == arr[mid + 1])
    49                                 {
    50                                     ret.Add(arr[mid]);
    51                                     ret.Add(arr[mid + 1]);
    52                                 }
    53                                 else
    54                                 {
    55                                     ret.Add(Math.Abs(arr[mid]) > arr[mid + 1] ? arr[mid + 1] : arr[mid]);
    56                                 }
    57                                 break;
    58                             }
    59                             low = mid + 1;
    60                         }
    61                     }
    62                 }
    63             }
    64 
    65             return ret;
    66         }

      解法三:

    View Code
     1         private static void binarySearch(int low, int high, IList<int> arr, ref List<int> ret)
     2         {
     3             while (low <= high)
     4             {
     5                 int mid = (low + high) / 2;
     6                 if (arr[mid] == 0)
     7                 {
     8                     ret.Add(arr[mid]);
     9                     break;
    10                 }
    11                 if (arr[mid] > 0) //中间位置为正数
    12                 {
    13                     if (arr[mid - 1] < 0) //中间位置前一个为负数
    14                     {
    15                         if (Math.Abs(arr[mid - 1]) == arr[mid])
    16                         {
    17                             ret.Add(arr[mid - 1]);
    18                             ret.Add(arr[mid]);
    19                         }
    20                         else
    21                         {
    22                             ret.Add(Math.Abs(arr[mid - 1]) > arr[mid] ? arr[mid] : arr[mid - 1]);
    23                         }
    24                         break;
    25                     }
    26                     high = mid - 1;
    27                     binarySearch(low, high, arr, ref ret);
    28                     break;
    29                 }
    30                 else //中间位置为负数
    31                 {
    32                     if (arr[mid + 1] > 0) //中间位置后一个为正数
    33                     {
    34                         if (Math.Abs(arr[mid]) == arr[mid + 1])
    35                         {
    36                             ret.Add(arr[mid]);
    37                             ret.Add(arr[mid + 1]);
    38                         }
    39                         else
    40                         {
    41                             ret.Add(Math.Abs(arr[mid]) > arr[mid + 1] ? arr[mid + 1] : arr[mid]);
    42                         }
    43                         break;
    44                     }
    45                     low = mid + 1;
    46                     binarySearch(low, high, arr, ref ret);
    47                     break;
    48                 }
    49             }
    50         }
    51 
    52         private static IEnumerable<int> GetABSMinValue3(IList<int> arr)
    53         {
    54             var ret = new List<int>();
    55             if (arr.Count < 2)
    56             {
    57                 ret.Add(arr[0]);
    58             }
    59             else
    60             {
    61                 if (arr[arr.Count - 1] <= 0)
    62                 {
    63                     ret.Add(arr[arr.Count - 1]);
    64                 }
    65                 else if (arr[0] >= 0)
    66                 {
    67                     ret.Add(arr[0]);
    68                 }
    69                 else
    70                 {
    71                     //方法三:二分法
    72                     binarySearch(0, arr.Count - 1, arr, ref ret);
    73                 }
    74             }
    75 
    76             return ret;
    77         }

      测试用例: 

    View Code
     1             var arr1 = new[] { -23, -22, -3, -2,-1, 1, 2, 3, 5, 20, 120 };
     2             var arr2 = new[] { -23, -22, -12, -6, -4 };
     3             var arr3 = new[] { 1, 22, 33, 55, 66, 333 };
     4             Console.WriteLine(string.Join(",", GetABSMinValue1(arr1)));
     5             Console.WriteLine(string.Join(",", GetABSMinValue1(arr2)));
     6             Console.WriteLine(string.Join(",", GetABSMinValue1(arr3)));
     7             Console.WriteLine(string.Join(",", GetABSMinValue2(arr1)));
     8             Console.WriteLine(string.Join(",", GetABSMinValue2(arr2)));
     9             Console.WriteLine(string.Join(",", GetABSMinValue2(arr3)));
    10             Console.WriteLine(string.Join(",", GetABSMinValue3(arr1)));
    11             Console.WriteLine(string.Join(",", GetABSMinValue3(arr2)));
    12             Console.WriteLine(string.Join(",", GetABSMinValue3(arr3)));
    13             Console.ReadKey();

      如果有更好的解决方案,请指教。谢谢大家!

    源码下载地址:GetABSMinValue.rar

  • 相关阅读:
    模板实现查找算法
    指针笔试题
    【查找算法】基于比较的查找算法(顺序查找、对分查找、分块查找)
    flask动态路由
    flask对json的内置处理模块jsonify
    pyquery和etree两个模块的区别
    单元测试初试
    求数组中子数组的最大值
    C语言小程序之读取文本文件中单词的个数并打印出频率最高的10个
    电梯去哪儿
  • 原文地址:https://www.cnblogs.com/tewuapple/p/2908583.html
Copyright © 2011-2022 走看看