您的位置:首页 > 其它

牛客网算法学习记录-二分搜索

2016-05-26 19:57 211 查看
定义局部最小的概念。arr长度为1时,arr[0]是局部最小。arr的长度为N(N>1)时,如果arr[0]<arr[1],那么arr[0]是局部最小;如果arr[N-1]<arr[N-2],那么arr[N-1]是局部最小;如果0<i<N-1,既有arr[i]<arr[i-1]又有arr[i]<arr[i+1],那么arr[i]是局部最小。
给定无序数组arr,已知arr中任意两个相邻的数都不相等,写一个函数,只需返回arr中任意一个局部最小出现的位置即可。

题意就是存在一个极小值,找到它。

int getLessIndex(vector<int> arr)

    {

        if(arr.empty())

            return -1;

        if(arr.size()==1||arr[0]<arr[1])

            return 0;

        if(arr[arr.size()-1]<arr[arr.size()-2])

            return arr.size()-1;

        int low=0,high=arr.size()-1,mid,res;

        while(low<=high)

        {

            mid=low+(high-low)/2;

            if(arr[mid]<arr[mid+1]&&arr[mid]<arr[mid-1]) //不用担心数组如果是单调递增导致数组越界的情况, 前面已经处理过单侧数组的情况了。

            {

                res=mid;

                break;

            }

            if(arr[mid]>arr[mid-1])

                high=mid-1;

            else

                low=mid+1;

        }

        return res;

    }

对于一个有序数组arr,再给定一个整数num,请在arr中找到num这个数出现的最左边的位置。

给定一个数组arr及它的大小n,同时给定num。请返回所求位置。若该元素在数组中未出现,请返回-1。

测试样例:
[1,2,3,3,4],5,3

返回:2

二分搜索:

int findPos(vector<int> arr, int n, int num) {

        // write code here

        int res = -1;

        if( n==1)

            return 0;

        if( n ==0)

            return -1;

        int low = 0 ;

        int high = arr.size() -1;

        int mid ;

        while(low<=high){

            mid = low + (high - low)/2;

            if(arr[mid] == num){

                res = mid ;

                high = mid -1; //向下移动是因为为升序,找到当前num结点 如果要找到最左边的结点则一定要向下移动。

            }

            

            else if(arr[mid]>num){

                high = mid - 1;

            }

            else if (arr[mid]<num){

                low = mid +1;

            }

            

        }

        return res;
    }

有一个有序数组arr,其中不含有重复元素,请找到满足arr[i]==i条件的最左的位置。如果所有位置上的数都不满足条件,返回-1。

给定有序数组arr及它的大小n,请返回所求值。

测试样例:
[-1,0,2,3],4

返回:2

观察到是整形数组,所以元素的增量至少为1,下标差量为1.所以如果arr[0]>n-1 或者arr[n-1]<0存在,则不可能存在arr[i] == i的情况。

假如arr[mid]>mid 那么根据上述条件 high = mid -1 才可能存在 arr[i] ==i

class Find {

public:

    int findPos(vector<int> arr, int n) {

        // write code here

        if(n==0)

            return -1;

        if(arr[0] > n-1 ||arr[n-1]<0){

            return -1;

        }

        int res=-1;

        int low = 0;

        int high = n-1;

        int mid = low + (high - low)/2;

        while(low<=high){   //必须有等于号

            if (arr[low] > low || arr[high] < high) {

                break;

            }

            mid = low + (high - low)/2;

            if(arr[mid]==mid){

                high = mid-1;

                res = mid;

            }

            else if (arr[mid]>mid){

                high = mid - 1;

            }

            else{

                low = mid + 1;

            }

        }

        return res;

    }

};

6.7

给定一棵完全二叉树的根节点root,返回这棵树的节点个数。如果完全二叉树的节点数为N,请实现时间复杂度低于O(N)的解法。

给定树的根结点root,请返回树的大小。

我有些写不来这种递归函数,参考答案如下。

思路大概是先求二叉树的最大层次,然后分左右子树去看层次是否相同,再根据二叉树结点个数和层次的关系去求解。(可能讲的有些模糊)

如果更快的求一个整数k的n次方。如果两个整数相乘并得到结果的时间复杂度为O(1),得到整数k的N次方的过程请实现时间复杂度为O(logN)的方法。

给定k和n,请返回k的n次方,为了防止溢出,请返回结果Mod 1000000007的值。

测试样例:
2,3

返回:8


思路:将指数部分转换成二进制,那么二进制对应的每位分别为K^1,K^2,K^3...

class QuickPower {

public:

    int getPower(int k, int N) {

        // write code here

        long result = 1;

        long k_n = k;

        vector<int> binary;

        transTenToTwo(binary,N);

        for(int i = 0 ;i<binary.size();i++){

            

            if(binary[i] == 1){

                result = result *k_n %1000000007;

            }

            k_n =( k_n *k_n)%1000000007;   //防止溢出

        }

        return result;

    }

    

    void transTenToTwo(vector<int> &vec,int num){

        while(num>0){

            vec.push_back(num%2);

            num = num/2;

        }   

    }

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: