二分查找的练习两题

一、搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。你可以假设数组中无重复元素。

示例 1: 输入: [1,3,5,6], 5 输出: 2

示例 2: 输入: [1,3,5,6], 2 输出: 1

示例 3: 输入: [1,3,5,6], 7 输出: 4

示例 4: 输入: [1,3,5,6], 0 输出: 0  

一般通过。

二分查找就是那种,通过一个中间值mid将数组(一般是有序)分两区间,[low,mid)和[mid+1,high) (一般是这样分,但也会根据题目有各种变式),判断target在哪个区间里,然后不断缩小搜索范围,直到区间只剩下一个数。这个数就算不是target,也是比target小的数字里最大的。

int searchInsert(vector<int>& nums, int target) {        

        int low=0;        

        int high=nums.size();       

         int mid;        

        while(low<high)       

         {                       

                mid=(low+high)/2;                  

                if(target==nums[mid])            

                {                

                        return mid;            

                }            

                else if(target>nums[mid])            

                {                                           

                        low=mid+1;            

                }            

                else if(target<nums[mid])            

                {                

                        high=mid;            

                }                   

‘         }                        

        return low;    

}

二、寻找重复数

给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

示例 1: 输入: [1,3,4,2,2]   输出: 2

示例 2: 输入: [3,1,3,4,2]   输出: 3

说明:

不能更改原数组(假设数组是只读的)。

只能使用额外的 O(1) 的空间。

时间复杂度小于 O(n2) 。

数组中只有一个重复的数字,但它可能不止重复出现一次。  

这题我在《剑指offer》上看过。因为对空间复杂度的限制,所以不能用哈希表。也不能上来直接就二分法,数组是无序的。

这题有个很关键的地方在于 “包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n)”,假设都没有重复的话,数字区间应该是[1,n+1]才对。根据这个思路,我们可以用二分法把数组分成两部分,用mid区分开。在[1~mid]这个部分进行元素的计数统计,统计总数count如果比mid来的大,说明这个区间里有重复的数字,对[mid+1,high]也是同理,统计其间的数字是否比high-mid来的大。

int countNum(vector<int>& nums,int start,int end)    {        //用来统计个数的

        int count=0;        

        int len=nums.size();        

        for(int i=0;i<len;i++)        

        {            

                if(nums[i]>=start&&nums[i]<=end)            

                {                                       

                        count++;            

                }        

        }        

        return count;    

}    

int findDuplicate(vector<int>& nums)     

{        

        int low=1;        

        int high=nums.size()-1; //4        

        int mid;//2        

        //分区间[1,2],[3,4]        

        while(low<=high)        

        {            

                //cout<<"查找"<<low<<"到"<<high<<endl;            

                mid=(high+low)/2;            

                //cout<<"mid:"<<mid<<endl;            

                if(high==low)            

                {                

                        return mid;            

                }            

                if(countNum(nums,low,mid)<=(mid-low+1))            

                {               

                        if(countNum(nums,mid+1,high)>(high-mid))                

                        {                    

                                    low=mid+1;                

                        }            

                }            
                else            

                {                   

                          high=mid;            

                }        

        }        

        return -1;    

}

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容