一道简单的面试题:竟然有90%的程序员不能把这个算法完全写正确。。。
2019-06-06 15:38
786 查看
前段时间,在论坛上看到有统计说有90%的程序员不能够写对简单的二分法。二分法不是很简单的吗? 这难道不是耸人听闻?
其实,二分法真的不那么简单,尤其是二分法的各个变种。 最最简单的二分法,就是从一个排好序的数组之查找一个key值。 如下面的程序。
/** * 二分查找,找到该值在数组中的下标,否则为-1 */ static int binarySerach(int[] array, int key) { int left = 0; int right = array.length - 1; // 这里必须是 <= while (left <= right) { int mid = (left + right) / 2; if (array[mid] == key) { return mid; } else if (array[mid] < key) { left = mid + 1; } else { right = mid - 1; } } return -1; }
这个程序,相信只要是一个合格的程序员应该都会写。 稍微注意一点, 每次移动left和right指针的时候,需要在mid的基础上+1或者-1, 防止出现死循环, 程序也就能够正确的运行。
但如果条件稍微变化一下, 你还会写吗?如,数组之中的数据可能可以重复,要求返回匹配的数据的最小(或最大)的下标;更近一步, 需要找出数组中第一个大于key的元素(也就是最小的大于key的元素的)下标,等等。 这些,虽然只有一点点的变化,实现的时候确实要更加的细心。 下面列出了这些二分检索变种的实现。
1、找出第一个与key相等的元素
// 查找第一个相等的元素 static int findFirstEqual(int[] array, int key) { int left = 0; int right = array.length - 1; // 这里必须是 <= while (left <= right) { int mid = (left + right) / 2; if (array[mid] >= key) { right = mid - 1; } else { left = mid + 1; } } if (left < array.length && array[left] == key) { return left; } return -1; }
2、找出最后一个与key相等的元素
// 查找最后一个相等的元素 static int findLastEqual(int[] array, int key) { int left = 0; int right = array.length - 1; // 这里必须是 <= while (left <= right) { int mid = (left + right) / 2; if (array[mid] <= key) { left = mid + 1; } else { right = mid - 1; } } if (right >= 0 && array[right] == key) { return right; } return -1; }
3、查找第一个等于或者大于Key的元素
// 查找第一个等于或者大于key的元素 static int findFirstEqualLarger(int[] array, int key) { int left = 0; int right = array.length - 1; // 这里必须是 <= while (left <= right) { int mid = (left + right) / 2; if (array[mid] >= key) { right = mid - 1; } else { left = mid + 1; } } return left; }
4、查找第一个大于key的元素
// 查找第一个大于key的元素 static int findFirstLarger(int[] array, int key) { int left = 0; int right = array.length - 1; // 这里必须是 <= while (left <= right) { int mid = (left + right) / 2; if (array[mid] > key) { right = mid - 1; } else { left = mid + 1; } } return left; }
5、查找最后一个等于或者小于key的元素
// 查找最后一个等于或者小于key的元素 static int findLastEqualSmaller(int[] array, int key) { int left = 0; int right = array.length - 1; // 这里必须是 <= while (left <= right) { int mid = (left + right) / 2; if (array[mid] > key) { right = mid - 1; } else { left = mid + 1; } } return right; }
6、查找最后一个小于key的元素
// 查找最后一个小于key的元素 static int findLastSmaller(int[] array, int key) { int left = 0; int right = array.length - 1; // 这里必须是 <= while (left <= right) { int mid = (left + right) / 2; if (array[mid] >= key) { right = mid - 1; } else { left = mid + 1; } } return right; }
接下来,大家可以对这四种变种算法进行相应的测试。
很多的时候,应用二分检索的地方都不是直接的查找和key相等的元素,而是使用上面提到的二分检索的各个变种,熟练掌握了这些变种,当你再次使用二分检索的检索的时候就会感觉的更加的得心应手了。
相关文章推荐
- 《编程珠玑》代码之路7:这个算法全世界程序员16年才写对,你肯定想不到竟然是这个
- (C#)一道看似简单却很难答得完全正确的关于多态的问题
- 一道简单的面试题,据说90%人不能在30分钟内做出来
- 华为一道面试题,不能用系统的字符串函数求对等数,用最简单的方法实现。
- 解决chrome字体不能小于12px (一道简单的面试题)
- 一道简单的面试题(求较小的值,不能用 比较运算符 if-else ?: while for 内嵌汇编 递归 第三方函数)(zt)
- 对一道算法面试题的理解
- 程序员面试题精选100题(57)-O(n)时间的排序[算法]
- 一道博弈的面试题及其算法正确性证明
- 一道简单的面试题
- 一道不简单又简单的Google面试题
- 一道简单的算法练习题试水下
- 程序员面试题精选100题(25)-在从1到n的正数中1出现的次数[算法]
- 一道简单题目的数据结构算法分析
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 引用类型传值(一道极难有人完全做对的面试题)
- 一道看似简单的面试算法题所隐藏的潜在意图
- 一道别致的算法面试题
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)