剑指offer 03.53Ⅰ.53Ⅱ. 查找算法(简单)

本文介绍了三种解决数组中重复数字的方法,包括使用标志数组、原地排序和哈希集,并提供了对应的Java代码实现。同时,对于查找排序数组中目标数字出现次数的问题,分别展示了遍历计数和二分查找两种策略。最后,针对寻找0到n-1中缺失数字的题目,给出了遍历和二分查找的解决方案。这些算法在处理数组问题时展现出不同的效率和适用场景。
摘要由CSDN通过智能技术生成

题目一:

剑指 Offer 03. 数组中重复的数字https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/

想法一:使用flag数组标记是否出现过

想法二:考虑到数字只有0~n-1,所以遍历将每个数字交换到顺序位置,当交换途中位置上数字已经正确时则为重复值

想法三:使用hashset.contains()判断唯一

代码:

//法一
class Solution {
    public int findRepeatNumber(int[] nums) {
        boolean[] flag= new boolean[nums.length];
        for (int i = 0; i < nums.length; i++) {
            if (flag[nums[i]]){
                return nums[i];
            }
            if (!flag[nums[i]]){
                flag[nums[i]]=true;
            }
        }
        return -1;
    }
}

//法二
class Solution {
    public int findRepeatNumber(int[] nums) {
        int i = 0;
        //"遍历"数组,将数字放在0~n-1顺序应在位置
        while(i < nums.length) {
            //实际上是在一个位置多exchange几次,直到换来了本位置应有的数字,才顺到下一位置
            if(nums[i] == i) {
                i++;
                continue;
            }
            //若已有数字在应在位置,则是重复
            if(nums[nums[i]] == nums[i]) 
                return nums[i];
            //在一个位置exchange几次
            int tmp=nums[i];
            nums[i]=nums[tmp];
            nums[tmp]=tmp;
        }
        //空数组返回-1
        return -1;
    }
}

//法三
class Solution {
    public int findRepeatNumber(int[] nums) {
        HashSet<Integer> set =new HashSet<>();
        for(int i=0;i<nums.length;i++){
            if(set.contains(nums[i]))
                return nums[i];
            set.add(nums[i]);
        }
        return -1;
    }
}

 结果一:

结果二:

 

结果三: 

题目二:

剑指 Offer 53 - I. 在排序数组中查找数字 Ihttps://leetcode-cn.com/problems/zai-pai-xu-shu-zu-zhong-cha-zhao-shu-zi-lcof/

代码:

//法一:遍历计数
class Solution {
    public int search(int[] nums, int target) {
        int count=0;
        for (int i = 0; i < nums.length; i++) {
            if(nums[i]==target)
                count++;
        }
        return count;
    }
}
//法二:二分法查找tar的左右边界
class Solution {
    public int search(int[] nums, int target) {
        return helper(nums, target) - helper(nums, target - 1);
    }
    int helper(int[] nums, int tar) {
        //二分法查找tar数字的右侧数字的位置(该位置可能越界)
        //如[5,7,7,8,8,10] 8,tar=8时返回5,tar=7时返回3
        //如[1] 1,tar=1时返回1,tar=0时返回0
        int i = 0, j = nums.length - 1;
        while(i <= j) {
            int m = (i + j) / 2;
            //临界点:i==j
            //二分法查找tar数字的 右侧数字 的位置
            if(nums[m] <= tar) 
                i = m + 1;
            else 
                j = m - 1;
        }
        return i;
    }
}
//法二的另一种写法
class Solution {
    public int search(int[] nums, int target) {
        int n=nums.length;
        int high=n-1;
        int low=0;
        int res=0;
        int mid=0;
        while(low<=high){
            mid=(low+high)/2;
            if(nums[mid]<target)
                low=mid+1;
            else
                high=mid-1;
            //low 第一个不小于target的
        }
        res=low;
        low=mid;
        high=n-1;
        while(low<=high){
            mid=(low+high)/2;
            if(nums[mid]<=target)
                low=mid+1;
            else
                high=mid-1;
            //low 第一个大于target的
        }
        return low-res;
    }
}

结果:

题目三:

剑指 Offer 53 - II. 0~n-1中缺失的数字https://leetcode-cn.com/problems/que-shi-de-shu-zi-lcof/

代码:

//法一:遍历
class Solution {
    public int missingNumber(int[] nums) {
        for (int i = 0; i < nums.length; i++) {
            if(nums[i]!=i)
                return i;
        }
        return nums.length;
    }
}
//法二:二分法
class Solution {
    public int missingNumber(int[] nums) {
        int i = 0, j = nums.length - 1;
        while(i <= j) {
            int m = (i + j) / 2;
            if(nums[m] == m) 
                i = m + 1;
            else 
                j = m - 1;
        }
        return i;
    }
}

结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值