百度面试题:求绝对值最小的数

参考了这篇博客的内容和思路: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

 

 

posted @ 2013-02-07 10:57  特务小强  阅读(866)  评论(4编辑  收藏  举报