首页 > 其他分享 >剑指Offer面试题3题目二:不修改数组找出重复的数字

剑指Offer面试题3题目二:不修改数组找出重复的数字

时间:2023-09-14 13:32:26浏览次数:40  
标签:面试题 数字 Offer int start numbers 数组 重复

一、题目

在一个长度为 n+1 的数组里的所有数字都在 1~n 的范围内,所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但不能修改输入的数组。例如,如果输入长度为 8 的数组{2, 3, 5, 4, 3, 2, 6, 7},那么对应的输出是重复的数字 2 或 3。

输入参数:一个整数数组numbers,数组长度length

输出参数:-1(代表输入参数出错),或者是重复的数字

二、解法

2.1分析1:辅助数组法

由于不能修改输入的数组,我们可以创建一个长度为 n+1的辅助数组,然后逐一将原数组的每个数字复制到辅助数组。如果原数组中被复制的数字是m,则把它复制到辅助数组下标为m的位置。如果下标为m的位置已经有数字了,则说明该数字重复。

该解法的空间复杂度是O(n)。

代码如下:

public int getDuplicate(int[] numbers){
  if(numbers == null || numbers.length <= 0){
    	return -1;
  }
  int[] s = new int[numbers.length];
  for(int i = 0;i < numbers.length;i++){
    s[numbers[i]] == 0 ? numbers[i]: -1;
    if(s[numbers[i]] == -1){
      return s[numbers[i]];
    }
  }
  return -1;
}

2.2分析2:二分查找的思路

在分析1的方法上进行改进,不需要额外的辅助空间。

假如没有重复数字,那么在从1~n的范围内只有n个数字,由于数字里包含超过n个数字,所以一定包含了重复的数字。

我们把1~n的数字从中间的数字m分为两部分,前面一半为1~m,后面一半为m+1~n。如果1~m的数字数目超过m,那么这一半的区域里面一定包含重复数字;否则另一半m+1~n的区间中一定包含重复的数字。我们可以继续把区间一分为二,直到找到一个重复的数字。这个过程和二分法很类似,只是多了一步统计区间中数字的数目。

public int getDuplicate(int[] numbers){
  if(numbers == null || numbers.length <= 0){
    	return -1;
  }
  int length = numbers.length
  int start = 1;
  int end = length -1;
  while(end >= start){
    int middle = ((end - start) >> 1) + start;
    int count = countRange(numbers,start,end);
    if(end == start){
      if(count > 1){
        return start;
      }else{
        break;
      }
    }
    if count >(middle - start +1)
      end = middle;
    else
      start = middle + 1;
  }
  return -1;
}

public int countRange(int[] numbers,int start,int end){
  if(numbers.length == 0){
    return 0;
  }
  int count = 0;
  for(int i = 0; i< numbers.length;i++){
    if(numbers[i]  >= start && numbers[i] <= end)
      count++;
    }
  return count;
}

标签:面试题,数字,Offer,int,start,numbers,数组,重复
From: https://blog.51cto.com/u_16244372/7469233

相关文章

  • 逗号分隔的字符串与List互转-----字符串与数组互转
    1.字符串转数组使用Java split()方法split()方法根据匹配给定的正则表达式来拆分字符串。注意:.、|和*等转义字符,必须得加\。多个分隔符,可以用|作为连字符。//字符串转数组java.lang.StringStringstr="0,1,2,3,4,5";String[]arr=str.split(",");//用......
  • 用c++ 实现 二分查找 前提是先把数组排列好
    #include<iostream>usingnamespacestd;//可以递归调用的二分查找intsearch(constint(&a)[10],intstart,intend,inttarget){ //基准情况:目标值超出范围,或者start>end,说明没有找到 if(target<a[start]||target>a[end]||start>end) return-1; //取二分......
  • var let 经典面试题(理解作用域)
    1 let是块级作用域,每次输出的时候要找的i不是同一个i,是各自块作用域的i,是不同的i,在第一个块作用域里i的值是0,第二个是1,以此类推,所以第一个console出来的值是不同的,是01234当单独的输出语句输出i的时候,它的作用域并没有i,所以它会报错,所以第二个console出来的值是iis......
  • LeetCode349 两个数组的交集
    LeetCode349 两个数组的交集https://leetcode.cn/problems/intersection-of-two-arrays/学习内容给两个数组,返回这两个数组的交集。如一个数组是22946,一个数组是1221,这两个数组的交集是2。用数组来保存交集,可能会没有去重。交集为元素2就可以了。这道题目用set来解决的一个比较好......
  • 索引常见面试题
    索引常见面试题什么是索引?索引是数据的目录,用来加快数据的搜索,类似书本的目录可以分为几个类型数据结构b+树索引,通过b+树存储索引,但是非叶子节点保存数据,叶子节点保存数据hash索引:通过hash计算得出索引位置fulltext索引:也叫全文索引(我不会介绍)物理存储聚簇索引:索引......
  • 大厂面试题:有了 G1 还需要其他垃圾回收器吗?
    Java全能学习+面试指南:https://javaxiaobear.cn今天我们主要来看下这两个高频的面试考题:G1 的回收原理是什么?为什么G1比传统GC回收性能好?为什么G1如此完美仍然会有ZGC?我们在上一篇中,简要的介绍了CMS垃圾回收器,下面我们简单回忆一下它的一个极端场景(而且是经常......
  • 剑指 Offer 41. 数据流中的中位数
    classMedianFinder{public:/**initializeyourdatastructurehere.*///注意小根堆的定义方式priority_queue<int,vector<int>,greater<int>>up;//小根堆,默认放从大到小后一半的数priority_queue<int>down;//大根堆,默认放从小到大排序前一半......
  • springcloud相关面试题
    (目录)springcloud相关面试题springcloud中网关起什么作用在SpringCloud中,网关起到了路由和过滤的作用。路由:网关通过配置路由规则,将请求转发到不同的服务实例上。它可以根据请求的URL、请求的HTTP方法、请求的Header等信息,将请求路由到相应的服务实例上。通过网关,可以实现......
  • Git常见的面试题
    在软件开发领域,Git是一个极为重要的版本控制系统,几乎每个开发者都需要掌握它。因此,在面试过程中,Git常常成为了面试官们用来考察候选人技能和经验的重要工具之一。以下是一些常见的Git面试题,希望它们能帮助你在面试中脱颖而出。什么是Git?Git是一个分布式版本控制系统,用于跟踪......
  • 数组(一)
    数组今日份学习为一维数组及二维数组的创建,初始化以及一些基础的使用。一维数组一维数组的创建分为两类:一是先声明,再用new关键字进行内存分配;先声明:数组元素类型数组名字[];【例】intstudent[];数组元素类型[]数组名字;【例】int[]student;(以上两种都是Java中对于数组的正......