【编程题目】一个数组是由一个递减数列左移若干位形成的,在这种数组中查找某一个数。☆

48.微软(运算):
一个数组是由一个递减数列左移若干位形成的,比如{4,3,2,1,6,5}
是由{6,5,4,3,2,1}左移两位形成的,在这种数组中查找某一个数。

我的思路:

非常麻烦:先是用二分法找最大的数的位置,再定位要找的数在哪个递减区间里,最后用普通的二分查找法找到。代码如下:

/*
48.微软(运算):
一个数组是由一个递减数列左移若干位形成的,比如{4,3,2,1,6,5}
是由{6,5,4,3,2,1}左移两位形成的,在这种数组中查找某一个数。
*/

#include <stdio.h>

int find(int * a, int len, int num)
{
    int begin = 0;
    int end = len - 1;
    int mid;
    int MaxNumLocation = -1;
    bool isfind = false;

    //首尾特殊处理
    if(a[0] == num)
        return 0;
    else if(a[len - 1] == num)
        return len - 1;
    else
    {
        //先用二分查找定位最大值位置
        while(end > begin + 1)
        {
            if(a[begin] > a[end])
            {
                MaxNumLocation = begin;
                break;
            }
            else
            {
                mid = begin + (end - begin) / 2;
                if(a[mid] > a[end])
                {
                    end = mid;
                }
                else
                {
                    begin = mid;
                }
            }
        }

        if(MaxNumLocation == -1)
        {
            MaxNumLocation = end;
        }

        //定位当前要找的数字所在的递减区间
        if(num > a[len - 1] && num < a[0]) //区间没有旋转过
        {
            begin = 0;
            end = len - 1;
        }
        else if(num > a[len - 1] && num > a[0]) //在旋转后的右半部分
        {
            begin = MaxNumLocation;
            end = len - 1;
        }
        else if(num < a[len - 1] && num < a[0])//在旋转后的左半部分
        {
            begin = 0;
            end = MaxNumLocation - 1;
        }
        else
        {
            printf("error!!!!");
        }

        //二分查找
        while(begin < end - 1)
        {
            mid = begin + (end - begin) / 2;
            if(a[mid] > num)
            {
                begin = mid;
            }
            else if(a[mid] < num)
            {
                end = mid;
            }
            else
            {
                return mid;
            }
        }

        if(a[begin] == num)
            return begin;
        else if(a[end] == num)
            return end;
        else
        {
            printf("error!");
            return -1;
        }

    }
}

int main()
{
    int a[6] = {6,4,2,0,10,8};
    int b = find(a, 6, 8);
    return 0;
}

在网上看答案,发现自己想得太复杂了

http://www.cnblogs.com/daniagger/archive/2012/06/11/2545533.html 里面介绍的挺好

A:任意将这个数组从中间分开,分成两个数组,则至少有一个数组单调递减,另一个数组则可以由递减数组左移若干位得到,所以我们在二分之后确定界限的时候必须考虑所有情况,即需要查找的数组在哪一个分区里。

首先我们需要判断哪一个分区是单调递减的分区,这可以通过比较arr[l]和arr[mid]来得到,如果是大于等于,则左分区是单调递减,否则是右分区;再通过判断要查找的值是否夹在递减分区中间来最终确定选择哪一个分区。

代码验证可行。

注意:其实自己也想过分类讨论,可是想得太多了,总是想找到数字所在的递减序列。其实不一定要界定出递减的序列边界,只要能一次排除一半的错误选项就可以实现二分查找了

#include <iostream>
using namespace std;

int FindData(int* arr,int value,int l,int r)
{
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(arr[mid]==value)
            return mid;
        else
        {
            if(arr[l]>=arr[mid])
            {
                if(value>arr[mid] && value<=arr[l])
                    r=mid-1;
                else
                    l=mid+1;
            }
            else
            {
                if(value<arr[mid] && value>=arr[r])
                    l=mid+1;
                else
                    r=mid-1;
            }
        }
    }
    return -1;
}

int main()
{
    int arr[]={6,4,2,0,10,8};
    int n;
    cin >>n;
    cout <<FindData(arr,n,0,5)<<endl;
    return 0;
}
时间: 2024-10-22 00:06:25

【编程题目】一个数组是由一个递减数列左移若干位形成的,在这种数组中查找某一个数。☆的相关文章

【目录】编程题目

编程题目 如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1) 一个数组是由一个递减数列左移若干位形成的,在这种数组中查找某一个数.☆ 请修改 append 函数,利用这个函数实现两个非降序链表的并集 一串首尾相连的珠子(m 个),有 N 种颜色(N<=10),取出其中一段,要求包含所有 N 中颜色,并使长度最短. 求一个有向连通图的割点,割点的定义是,如果除去此节点和与其相关的边, 有向图不再连通 有 n 个长为 m+1 的字符串,如果某个字符串的最后 m 个字符与某个字符串的前

在左移的递减数组中查找某数 【微软面试100题 第四十八题】

题目要求: 一个数组是由一个递减数列左移若干位形成的,比如{4,3,2,1,6,5}是由{6,5,4,3,2,1,}左移两位形成的,在这种数组中查找某个数. 题目分析: 方法1 逐个查找,遍历一遍数组,时间复杂度O(N). 方法2 二分查找,时间复杂度O(logN).具体分析见下图: 代码实现: #include <iostream> using namespace std; int Helper(int a[],int k,int s,int t); int FindKInArray(int

【编程题目】求一个数组的最长递减子序列 比如{9,4,3,2,5,4,3,2}的最长递减子序列为{9,5, 4,3,2}

47.创新工场(算法):求一个数组的最长递减子序列 比如{9,4,3,2,5,4,3,2}的最长递减子序列为{9,5,4,3,2} 思路:动态规划 从最后一个数字开始,计算以当前数字其实的序列的最长递减子序列. 每次找最长子序列,都扫描它之前求得的子序列中最长,且第一个数字比当前数字小的. 如: 第一个数字 2, 最大长度 1, 下一个数字是 第 7 个 第二个数字 3,  最大长度 2, 下一个数字是 第 7 个 第三个数字 4,  最大长度 3, 下一个数字是 第 6 个 第四个数字 5, 

【编程题目】输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。

第 14 题(数组):题目:输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字.要求时间复杂度是 O(n).如果有多对数字的和等于输入的数字,输出任意一对即可.例如输入数组 1.2.4.7.11.15 和数字 15.由于 4+11=15,因此输出 4 和 11. 要求时间是O(n)肯定就只能扫描一遍. 又有两个数字要找,那就只能一个从头向后找 一个从后向前找 初始把大值设为最后一个数, 小值设为第一个数,如果数字和大于和,则减小大数的数值, 反之增大小

算法 - 求一个数组的最长递减子序列(C++)

//**************************************************************************************************** // // 求一个数组的最长递减子序列 - C++ - by Chimomo // // 题目: 求一个数组的最长递减子序列,比方{8, 14, 6, 2, 8, 14, 3, 2, 7, 4, 7, 2, 8, 101, 23, 6, 1, 2, 1, 1}的最长递减子序列为{14.8,3.

【编程题目】n 个数字(0,1,…,n-1)形成一个圆圈,从数字 0 开始

第 18 题(数组):题目:n 个数字(0,1,…,n-1)形成一个圆圈,从数字 0 开始,每次从这个圆圈中删除第 m 个数字(第一个为当前数字本身,第二个为当前数字的下一个数字).当一个数字删除后,从被删除数字的下一个继续删除第 m 个数字.求出在这个圆圈中剩下的最后一个数字. 思路:看到这道题,直觉是不难,模拟一下过程就好了.我用的是数组来表示的,用first表示当前第一个数字是哪一个数,若删除一个数字则将后面的数字平移到前面. /* 第 18 题(数组): 题目:n 个数字(0,1,…,n

【编程题目】对于一个整数矩阵,存在一种运算,对矩阵中任意元素加一时,需要其相邻(上下左右)某一个元素也加一

45.雅虎(运算.矩阵):1.对于一个整数矩阵,存在一种运算,对矩阵中任意元素加一时,需要其相邻(上下左右)某一个元素也加一,现给出一正数矩阵,判断其是否能够由一个全零矩阵经过上述运算得到. 这道题,是我目前为止做过的最最最最最麻烦.最繁琐的题目了. 思路: 把输入的矩阵一步步还原成 0 矩阵 一个数字,只可能伴随着它上下左右四个方向的数字变化. ①如果数字比它周围四个数的和要大,那么一定不满足条件. ②如果数字小于等于四周的数字和,且其四周仅有一个数字不为0: 不为0的那个周围数字的大小 -=

【编程题目】求一个矩阵中最大的二维矩阵(元素和最大)

35.(矩阵)求一个矩阵中最大的二维矩阵(元素和最大).如:1 2 0 3 42 3 4 5 11 1 5 3 0中最大的是:4 55 3要求:(1)写出算法;(2)分析时间复杂度;(3)用 C 写出关键代码 早上灭小题! /* 35.(矩阵) 求一个矩阵中最大的二维矩阵(元素和最大).如: 1 2 0 3 4 2 3 4 5 1 1 1 5 3 0 中最大的是: 4 5 5 3 要求:(1)写出算法;(2)分析时间复杂度;(3)用 C 写出关键代码 */ #include <stdio.h>

[编程之美]写一个函数,返回一个数组中所有元素被第一个元素除的结果

题目: 写一个函数,返回一个数组中所有元素被第一个元素除的结果: 错误的版本: void DivArray(int *array, int n) { for (int i = 0; i < n; ++i) { array[i] /= array[0]; } } 错误原因:在循环的第一步,第一个元素就变成了1,然后再用它去除以其他元素,就不符合题目要求了 改进: 1:使用其他变量保存第一个元素: void DivArray3(int *array, int n) { assert(array !=