《Cracking the Coding Interview》——第11章:排序和搜索——题目3
2014-03-21 21:26
453 查看
2014-03-21 20:55
题目:给定一个旋转过的升序排序好的数组,不知道旋转了几位。找出其中是否存在某一个值。
解法1:如果数组的元素都不重复,那么我的解法是先找出旋转的偏移量,然后进行带偏移量的二分搜索。两个过程都是对数级的。
代码:
解法2:如果数组的元素可能存在重复,那么我的思路仍然是先二分查找找出偏移量,然后执行带偏移量的二分搜索。不过,在找偏移量的过程中可能会出现无法决定向左还是向右的情况,比如这两个例子{1, 3, 1, 1, 1}{1, 1, 1, 3, 1},在第一次二分时,左中右的元素都是‘1’,无法确定应该往哪边走。这时就得扫描整段,{1, 1, 1}全部是同一元素,{1, 3, 1}存在不同元素,所以应该选择{1, 3, 1}进行二分,因为在首尾相同的情况下,中间如果有不同元素的话,表示旋转的偏移量应该会落在这个区间里。找到偏移量以后,之后的查找就是严格二分的了。
代码:
题目:给定一个旋转过的升序排序好的数组,不知道旋转了几位。找出其中是否存在某一个值。
解法1:如果数组的元素都不重复,那么我的解法是先找出旋转的偏移量,然后进行带偏移量的二分搜索。两个过程都是对数级的。
代码:
// 11.3 Given a sorted array rotated by a few positions, find out if a value exists in the array. // Suppose all elements in the array are unique. #include <algorithm> #include <vector> #include <cstdio> using namespace std; int rotatedBinarySearch(vector<int> &v, int n, int key) { int offset; if ((int)v.size() < n || n <= 0) { return -1; } int ll, rr, mm; if (v[0] < v[n - 1]) { offset = 0; } else { ll = 0; rr = n - 1; while (rr - ll > 1) { mm = (ll + rr) / 2; if (v[mm] > v[ll]) { ll = mm; } else { rr = mm; } } offset = rr; } ll = 0; rr = n - 1; while (ll <= rr) { mm = (ll + rr) / 2; if (key < v[(mm + offset) % n]) { rr = mm - 1; } else if (key > v[(mm + offset) % n]) { ll = mm + 1; } else { return (mm + offset) % n; } } return -1; } int main() { int n; int i; vector<int> v; while (scanf("%d", &n) == 1 && n > 0) { v.resize(n); for (i = 0; i < n; ++i) { scanf("%d", &v[i]); } scanf("%d", &i); printf("%d\n", rotatedBinarySearch(v, n, i)); } return 0; }
解法2:如果数组的元素可能存在重复,那么我的思路仍然是先二分查找找出偏移量,然后执行带偏移量的二分搜索。不过,在找偏移量的过程中可能会出现无法决定向左还是向右的情况,比如这两个例子{1, 3, 1, 1, 1}{1, 1, 1, 3, 1},在第一次二分时,左中右的元素都是‘1’,无法确定应该往哪边走。这时就得扫描整段,{1, 1, 1}全部是同一元素,{1, 3, 1}存在不同元素,所以应该选择{1, 3, 1}进行二分,因为在首尾相同的情况下,中间如果有不同元素的话,表示旋转的偏移量应该会落在这个区间里。找到偏移量以后,之后的查找就是严格二分的了。
代码:
// 11.3 Given a sorted array rotated by a few positions, find out if a value exists in the array. // Suppose the array may contain duplicates, what's it gonna be then? #include <algorithm> #include <vector> #include <cstdio> using namespace std; int rotatedBinarySearch(vector<int> &v, int n, int key) { int offset; if ((int)v.size() < n || n <= 0) { return -1; } int ll, rr, mm; int i; ll = 0; rr = n - 1; while (rr - ll > 1 && v[ll] == v[rr]) { mm = (ll + rr) / 2; if (v[mm] > v[ll]) { ll = mm; break; } else if (v[mm] < v[ll]) { rr = mm; break; } else { for (i = ll; i < mm - 1; ++i) { if (v[i] != v[i + 1]) { break; } } if (i < mm - 1) { rr = mm; break; } for (i = mm; i < rr - 1; ++i) { if (v[i] != v[i + 1]) { break; } } if (i < rr - 1) { break; } // if all elements are the same, it ends here return (v[0] == key) ? 0 : -1; } } if (v[ll] < v[rr]) { offset = 0; } else { // here it is guaranteed v[ll] != v[rr] while (rr - ll > 1) { mm = (ll + rr) / 2; if (v[mm] >= v[ll]) { ll = mm; } else { rr = mm; } } offset = rr; } // the binary search part remains the same, difference lies in how we find the 'offset'. ll = 0; rr = n - 1; while (ll <= rr) { mm = (ll + rr) / 2; if (key < v[(mm + offset) % n]) { rr = mm - 1; } else if (key > v[(mm + offset) % n]) { ll = mm + 1; } else { return (mm + offset) % n; } } return -1; } int main() { int n; int i; vector<int> v; while (scanf("%d", &n) == 1 && n > 0) { v.resize(n); for (i = 0; i < n; ++i) { scanf("%d", &v[i]); } scanf("%d", &i); printf("%d\n", rotatedBinarySearch(v, n, i)); } return 0; }
相关文章推荐
- 《Cracking the Coding Interview》——第11章:排序和搜索——题目6
- 《Cracking the Coding Interview》——第11章:排序和搜索——题目7
- 《Cracking the Coding Interview》——第11章:排序和搜索——题目1
- 《Cracking the Coding Interview》——第11章:排序和搜索——题目8
- 《Cracking the Coding Interview》——第11章:排序和搜索——题目2
- 《Cracking the Coding Interview》——第11章:排序和搜索——题目4
- 《Cracking the Coding Interview》——第11章:排序和搜索——题目5
- Cracking the Coding Interview 题目分析笔记—— Array and String
- 《Cracking the Coding Interview》——第13章:C和C++——题目7
- 《Cracking the Coding Interview》——第14章:Java——题目5
- 《Cracking the Coding Interview》——第1章:数组和字符串——题目6
- 《Cracking the Coding Interview》——第3章:栈和队列——题目3
- 《Cracking the Coding Interview》——第17章:普通题——题目12
- 《Cracking the Coding Interview》——第18章:难题——题目11
- 《Cracking the Coding Interview》——第4章:树和图——题目3
- 《Cracking the Coding Interview》——第6章:智力题——题目1
- 《Cracking the Coding Interview》——第9章:递归和动态规划——题目3
- 《Cracking the Coding Interview》——第10章:可扩展性和存储空间限制——题目7
- 《Cracking the Coding Interview》——第13章:C和C++——题目8
- 《Cracking the Coding Interview》——第14章:Java——题目6