剑指offer day4

106 阅读1分钟

刷题计划(第4天)

时间:2022.4.19

题数:4

题目类型:排序&哈希&二分

1. 数组中重复的数字

找出数组中重复的数字。在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

第一次尝试了最简单的方法:利用哈希,用c来写比较快

int findRepeatNumber(int* nums, int numsSize){
    int hashTable[100001]={0};
    for(int i=0;i<numsSize;i++){
        hashTable[nums[i]]++;
        if(hashTable[nums[i]]>=2){
            return nums[i];
        }
    }
    return -1;//题目范围是0到n
}

image.png

第二次采用排序,如果前后一样自然成功
class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        for(int i=0;i<nums.size();i++){
            if(nums[i]==nums[i+1]){
                return nums[i];
            }
        }
        return -1;
    }
};

image.png

2. 在排序数组中查找数字 I

统计一个数字在排序数组中出现的次数。

image.png

明显采用二分法,如下:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int i=0,j=nums.size()-1;
        while(i<=j){
            int mid=(j-i)/2+i;
            if(nums[mid]<target){
                i=mid+1;
            }else if(nums[mid]>target){
                j=mid-1;
            }else{
               if(nums[j]!=target){
                   j--;
               }else if(nums[i]!=target){
                   i++;
               }else{
                   break;
               }
            }
        }
        return j-i+1;
    }
};

image.png

3. 0~n-1中缺失的数字

一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字

int missingNumber(int* nums, int numsSize){
    int left=0,right=numsSize-1;
    while(left<=right){
        int mid=left+(right-left)/2;
        if(nums[mid]!=mid){
            right=mid-1;
        }else{
            left=mid+1;
        }
    }
    return left;
    
}

image.png

4. 二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

image.png

如题:

int search(int* nums, int numsSize, int target){
    int left=0,right=numsSize-1;
    while(left<=right){
        int mid=(right-left)/2+left;
        if(nums[mid]>target){
            right=mid-1;
        }else if(nums[mid]<target){
            left=mid+1;
        }else return mid;
    }
    return -1;
}

总结

对于有序数组,大概率为二分查找,左右指针一直缩小范围直到找到目标值位置,没找到就返回-1