2014-03-21 20:55

题目:给定一个旋转过的升序排序好的数组,不知道旋转了几位。找出其中是否存在某一个值。

解法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 <= ) {
return -;
} int ll, rr, mm; if (v[] < v[n - ]) {
offset = ;
} else {
ll = ;
rr = n - ;
while (rr - ll > ) {
mm = (ll + rr) / ;
if (v[mm] > v[ll]) {
ll = mm;
} else {
rr = mm;
}
}
offset = rr;
} ll = ;
rr = n - ;
while (ll <= rr) {
mm = (ll + rr) / ;
if (key < v[(mm + offset) % n]) {
rr = mm - ;
} else if (key > v[(mm + offset) % n]) {
ll = mm + ;
} else {
return (mm + offset) % n;
}
}
return -;
} int main()
{
int n;
int i;
vector<int> v; while (scanf("%d", &n) == && n > ) {
v.resize(n);
for (i = ; i < n; ++i) {
scanf("%d", &v[i]);
}
scanf("%d", &i);
printf("%d\n", rotatedBinarySearch(v, n, i));
} return ;
}

解法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 <= ) {
return -;
} int ll, rr, mm;
int i; ll = ;
rr = n - ;
while (rr - ll > && v[ll] == v[rr]) {
mm = (ll + rr) / ;
if (v[mm] > v[ll]) {
ll = mm;
break;
} else if (v[mm] < v[ll]) {
rr = mm;
break;
} else {
for (i = ll; i < mm - ; ++i) {
if (v[i] != v[i + ]) {
break;
}
}
if (i < mm - ) {
rr = mm;
break;
}
for (i = mm; i < rr - ; ++i) {
if (v[i] != v[i + ]) {
break;
}
}
if (i < rr - ) {
break;
} // if all elements are the same, it ends here
return (v[] == key) ? : -;
}
} if (v[ll] < v[rr]) {
offset = ;
} else {
// here it is guaranteed v[ll] != v[rr]
while (rr - ll > ) {
mm = (ll + rr) / ;
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 = ;
rr = n - ;
while (ll <= rr) {
mm = (ll + rr) / ;
if (key < v[(mm + offset) % n]) {
rr = mm - ;
} else if (key > v[(mm + offset) % n]) {
ll = mm + ;
} else {
return (mm + offset) % n;
}
} return -;
} int main()
{
int n;
int i;
vector<int> v; while (scanf("%d", &n) == && n > ) {
v.resize(n);
for (i = ; i < n; ++i) {
scanf("%d", &v[i]);
}
scanf("%d", &i);
printf("%d\n", rotatedBinarySearch(v, n, i));
} return ;
}

《Cracking the Coding Interview》——第11章:排序和搜索——题目3的更多相关文章

  1. Cracking the coding interview 第一章问题及解答

    Cracking the coding interview 第一章问题及解答 不管是不是要挪地方,面试题具有很好的联系代码总用,参加新工作的半年里,做的大多是探索性的工作,反而代码写得少了,不高兴,最 ...

  2. 《Cracking the Coding Interview》读书笔记

    <Cracking the Coding Interview>是适合硅谷技术面试的一本面试指南,因为题目分类清晰,风格比较靠谱,所以广受推崇. 以下是我的读书笔记,基本都是每章的课后习题解 ...

  3. Cracking the coding interview

    写在开头 最近忙于论文的开题等工作,还有阿里的实习笔试,被虐的还行,说还行是因为自己的水平或者说是自己准备的还没有达到他们所需要人才的水平,所以就想找一本面试的书<Cracking the co ...

  4. Cracking the coding interview目录及资料收集

    前言 <Cracking the coding interview>是一本被许多人极力推荐的程序员面试书籍, 详情可见:http://www.careercup.com/book. 第六版 ...

  5. Cracking the Coding Interview(Trees and Graphs)

    Cracking the Coding Interview(Trees and Graphs) 树和图的训练平时相对很少,还是要加强训练一些树和图的基础算法.自己对树节点的设计应该不是很合理,多多少少 ...

  6. Cracking the Coding Interview(Stacks and Queues)

    Cracking the Coding Interview(Stacks and Queues) 1.Describe how you could use a single array to impl ...

  7. 二刷Cracking the Coding Interview(CC150第五版)

    第18章---高度难题 1,-------另类加法.实现加法. 另类加法 参与人数:327时间限制:3秒空间限制:32768K 算法知识视频讲解 题目描述 请编写一个函数,将两个数字相加.不得使用+或 ...

  8. 《Cracking the Coding Interview》——第11章:排序和搜索——题目4

    2014-03-21 21:28 题目:给定一个20GB大小的文本文件,每一行都是一个字符串.请设计方法将这个文件里的字符串排序. 解法:请看下面的注释. 代码: // 11.4 Given a fi ...

  9. 《Cracking the Coding Interview》——第11章:排序和搜索——题目2

    2014-03-21 20:49 题目:设计一种排序算法,使得anagram排在一起. 解法:自定义一个comparator,使用额外的空间来统计字母个数,然后比较字母个数. 代码: // 11.2 ...

随机推荐

  1. 【LOJ6043】「雅礼集训 2017 Day7」蛐蛐国的修墙方案(搜索技巧题)

    点此看题面 大致题意: 给你一个长度为\(n\)的排列\(p\),要求构造一个合法的括号序列,使得如果第\(i\)个位置是左括号,则第\(p_i\)个位置一定是右括号. 暴搜 很容易想出一个暴搜. 即 ...

  2. 种类并查集,Poj(1703)

    题目链接:http://poj.org/problem?id=1703 第一次做种类并查集,有的地方还不是很清楚,想了一上午,有点明白了,这里记录一下. 这里我参考的红黑联盟的题解. 关键:种类并查集 ...

  3. 如何迅速掌握并提高linux运维技能(收藏文)

    如何迅速掌握并提高linux运维技能   文章来源于南非蚂蚁   之前曾经写过一篇如何学习Linux的文章,得到了很多反馈,大家都在分享自己的学习经验和体会,并且也提出了不少意见和建议.学习这个事情其 ...

  4. python 面向对象(三)--继承和多态

    在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类.父类或超类(Base class.Supe ...

  5. OnCollisionEnter和OnTriggerEnter

    之前对这两个的用法不是特别清楚,重新学习了下,再做个测试看看效果如何: 1.新建一个场景test 2.添加一个cube,点击Inspector面板会发现系统已经默认添加了Box collisder组件 ...

  6. 奇异值分解(SVD)和最小二乘解在解齐次线性超定方程中的应用

    奇异值分解,是在A不为方阵时的对特征值分解的一种拓展.奇异值和特征值的重要意义相似,都是为了提取出矩阵的主要特征. 对于齐次线性方程 A*X =0;当A的秩大于列数时,就需要求解最小二乘解,在||X| ...

  7. Spring 学习之bean的理解

    前言:对于使用Spring框架的开发人员来说,我们主要做的主要有两件事情:①开发Bean;②配置Bean;而Spring帮我们做的就是根据配置文件来创建Bean实例,并调用Bean实例的方法来完成“依 ...

  8. 数据库可视化工具简介以及pymysql的使用

    1.可视化工具Navicat 我们自己开发测试时,可以使用该可视化工具,以图形界面的形式操作数据库 在生产环境中,为了显示自己的逼格,一般不建议使用它 官网下载:https://www.navicat ...

  9. 分页查询关键代码 多条件查询关键代码 删除选中商品关键代码 修改要先回显再修改 修改要先回显再修改 同一业务集中使用同一servlet的方法

    分页查询关键代码: 通过servlet转发回来的各种信息进行分页的设计(转发回的信息有 分页查询的List集合 查询的页码 查询的条数 查询的数据库总条数 查询的总页码) 从开始时循环10次出现十个数 ...

  10. DateTools,可能是最好用的iOS日期工具库

    项目简介 DateTools 用于提高Objective-C中日期和时间相关操作的效率.灵感来源于 DateTime和Time Period Library. 项目主页: DateTools 最新示例 ...