Skip to content

Instantly share code, notes, and snippets.

@luangong
Last active February 6, 2017 22:35
Show Gist options
  • Save luangong/4663453 to your computer and use it in GitHub Desktop.
Save luangong/4663453 to your computer and use it in GitHub Desktop.
陈利人老师微博面试编程题:一个有序数组(从小到大排列),数组中的数据有正有负,求这个数组中的最小绝对值。微博地址:http://weibo.com/1915548291/zgH8XdILh 解决思路:二分查找。注意边界情况的处理
/**
* 陈利人老师微博面试编程题:一个有序数组(从小到大排列),数组中的数据有正有负,
* 求这个数组中的最小绝对值。
*
* Sample Input
*
* -4 -2 -1 2 3 5
* -2 0 3 5 8
* -8 -6 -3 -2 1
*
* http://weibo.com/1915548291/zgH8XdILh
*
* 解决思路:二分查找
*/
#include <iostream>
#include <sstream>
#include <limits>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;
int minAbs(int *A, int beg, int end) {
if (beg >= end) {
return numeric_limits<int>::max();
}
// 如果最左边最小的数大于或等于 0,则右边的数必然为非负且绝对值不小于此数,
// 所以最左边的数就是要求的最小的绝对值
if (A[beg] >= 0) {
return A[beg];
}
// 如果最右边最大的数小于或等于 0,则左边的数必然为非正且绝对值不小于此数,
// 所以最右边的数就是要求的最小的绝对值(注意要取反)
if (A[end-1] <= 0) {
return -A[end-1];
}
// 否则进行二分,求得数组中间的数
int mid = beg + (end - beg) / 2;
// 如果中间的数为非负,那么可以排除掉右半边的数
if (A[mid] >= 0) {
return min(A[mid], minAbs(A, beg, mid));
} else { // 否则排除掉左半边的数
return min(-A[mid], minAbs(A, mid + 1, end));
}
}
int main(int argc, char **argv) {
// 输入数据有多组,每组占一行,各个数字间用空格隔开
string line;
while (getline(cin, line)) {
istringstream strm(line);
vector<int> vec;
copy(istream_iterator<int>(strm),
istream_iterator<int>(), back_inserter(vec));
sort(vec.begin(), vec.end());
cout << minAbs(&vec[0], 0, vec.size()) << endl;
}
return 0;
}
@luangong
Copy link
Author

luangong commented Feb 2, 2017

@darrenhp 你的思路是对的,很简洁,这个题目是 N 年前的了,当时没想到,没必要自己手写二分查找算法

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment