• 数组中重复的数字


    题目描述

    在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
    返回描述:
    如果数组中有重复的数字,函数返回true,否则返回false。
    如果数组中有重复的数字,把重复的数字放到参数duplication[0]中。(ps:duplication已经初始化,可以直接赋值使用。)

    思路分析

    最暴力的解法:对数组进行排序,排序后的数组,比较两个相邻的数是否相等 ,排序一个长度为n的数组为O(nlogn).该方法对原数组进行了修改

    利用哈希表的不可重复性:对数组遍历一边,如果表中存在这个元素,则记录dup中,返回true,否则添加 时间复杂度O(n),空间复杂度,是一个大小为O(n)大小的哈希表 ,对原数组没有修改,且能知道第一次出现重复的值

    import java.util.*;
    public class Solution {
        public boolean duplicate(int numbers[],int length,int [] duplication) {
            if(numbers==null||length<0){
                return false;
            }
           HashSet<Integer> set= new HashSet();
           for(int i=0;i<length;i++){
               if(set.contains(numbers[i])){
                   duplication[0]=numbers[i];
                   return true;
               }
               set.add(numbers[i]);
           }
           return false;
        }
    }
    

    上述都没有用到题目中所给的所有数字都在0到n-1的范围内这个条件,思考一下如果数组没有重复值,那么长度为n的数组中的值肯定能和0~n-1这些数值中的值一一对应起来,所以,我们可以让原始数组的每一个下标都对应下标的值,如果在交换的过程中发现,发现与下标对应的值相等则说明找到

    public boolean duplicate(int numbers[],int length,int [] duplication) {
            if(numbers==null||length<=0){
                return false;
            }
            for(int i=0;i<length;i++){
                while(numbers[i]!=i){
                    if(numbers[i]==numbers[numbers[i]]){
                        duplication[0]=numbers[i];
                        return true;
                    }
                    swap(numbers,i,numbers[i]);
                }
            }
    
            return false;
        }
    
    
        public void swap(int[] nums,int i,int j){
            int temp=nums[i];
            nums[i]=nums[j];
            nums[j]=temp;
        }
    
    

    注意,此方法只能找到任意一个重复的值,但找不到第一个重复的值,(例如,6,3,2,0,2,5,0)该程序输出重复的值0但正确应该是 2,所以要看清楚题目

    拓展:在一个长度为n+1的数组里的所有数字都在1到n的范围内。所以数组至少有一个数字是重复的。请找出数组中任意一个重复的数字。但不能修改数组。

    可以使用O(n)的额外空间,像上述那样解决问题 。下面是避免使用O(n)的辅助空间

      /**
         * 在一个长度为n+1的数组里的所有数字都在1到n的范围内。所以数组至少有一个数字是重复的。请找出数组中任意一个重复的数字。但不能修改数组
         */
    
        //思路:在数字范围1...n上二分,对每次的左半部分 若果,数组中的数字在这个范围上个数小于二分长度,那右半部分一定有重复的数字,如果大于二分长度
        //一定在左半部分,依次递归,直到不能再分时结束递归
        int dup[] = new int[1];
        public int getDuplication(int[] nums, int length,int start, int end) {
            if (nums == null || nums.length == 0) {
                return -1;
            }
            if (start == end) {
                dup[0] = start;
                return start;
            }
            int mid = start + ((end - start) >> 1);
    
            int i = CountRange(nums, length, start, mid);//每次递归都计算出左范围,数组中有的个数
    
            if (i > (mid - start + 1)) {//左边这个范围上一定有重复的  继续递归
                getDuplication(nums, length, start, mid);
            } else {//
                getDuplication(nums, length, mid+1, end);
            }
    
            return dup[0];
        }
        
        /*
        数组在这个start ...end长度范围上有多少个值
         */
        public int CountRange(int[] nums, int length, int start, int end) {
            int count=0;
            if (nums == null) {
                return -1;
            }
            for (int i = 0; i < length; i++) {
                if (nums[i] >= start && nums[i] <= end) {
                    count++;
                }
            }
            return count;
    
        }
    
  • 相关阅读:
    3星|《中国古城墙》:重要的古城墙的资料汇集
    bindingSource具体使用案例
    WPF第三方控件盘点
    FluentValidation具体使用案例
    Visual Studio 版本管理从TFS迁移到SVN
    Image.FromStream与Image.FromFile使用区别
    判断图片的格式的方法
    WCF测试小程序
    使用AutoMapper 处理DTO数据对象的转换
    获取mac地址和IP地址方式
  • 原文地址:https://www.cnblogs.com/qingfeng5438/p/13927021.html
Copyright © 2020-2023  润新知