剑指offer03-寻找一维数组中重复的数字

2024-02-28 05:32

本文主要是介绍剑指offer03-寻找一维数组中重复的数字,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.题目描述

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

 Input:{2, 3, 1, 0, 2, 5}​Output:2

2.题目解析

case1: 一维数组在内存中占据连续的空间,因此我们可以根据下标定位对应的元素,总时间复杂度是O(n),空间复杂度是O(1)

case2: 不修改数组找出重复的数字,我们可以借助一个辅助数组,需要O(n)空间

case3: 不修改数组找出重复的数字,我们尝试使用二分查找方式,如果输入长度n的数组,总时间复杂度为O(nlogn),空间复杂度是O(1),与case2相比相当于以时间换空间。需要指出这种算法没法找出所有重复的数字

收获:要学会根据面试官要求,是找出任意一个还是全部重复数字,性能上,是时间效率优先还是空间效率优先。选择的算法也是不同的,需要和面试官交流。

3.代码-根据数组下标

package cn.swordOffer.num01;/*** @author GONG* @version 1.0* @date 2020/11/17 10:20* 在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1* 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,* 也不知道每个数字重复了几次。请找出数组中任意一个重复的数字* eg:{2, 3, 1, 0, 2, 5, 3},返回2或者3*/
public class FindDuplicateElementsByIndex {public int getDuplicate(int[] nums) {int res = -1;int len = nums.length;// 判空if (len <= 0) return -1;for (int i = 0; i < len; i++) {//有[0, n-1]范围外的数据if (nums[i] < 0 || nums[i] > len - 1) return -1;// 如果数组下标不等于数据中的值while (nums[i] != i) {// 如果相同表示,出现了重复数字if (nums[i] == nums[nums[i]])return nums[i];// 如果不相同,交换两个位置,交换之后,有个位置 nums[i]=i// 注意交换的顺序,如果temp = num[i]是不可以的int temp = nums[nums[i]];nums[nums[i]] = nums[i];nums[i] = temp;}
//            System.out.println(i + "=========" + Arrays.toString(nums));}return res;}public static void main(String[] args) {FindDuplicateElementsByIndex f = new FindDuplicateElementsByIndex();int nums[] = {2, 3, 1, 1, 0, 5, 4};int ans = f.getDuplicate(nums);System.out.println((ans == -1) ? "没有重复数字" : "其中重复数字是" + ans);}
}

4.代码-原数组上面使用二分查找法

package cn.swordOffer.num01;import java.util.Arrays;/*** @author GONG* @version 1.0* @date 2020/11/17 10:20* <p>* 给定一个数组,查找其是否有重复元素,如果有,任意返回一个重复元素* eg:{2, 3, 1, 0, 2, 5, 3},返回2或者3*/
public class FindDuplicateElementsByBinarySearch {public int getDuplicate(int[] nums) {// 判空int len = nums.length;if (len <= 0) return -1;// 使用二分法int start = 0;int end = len - 1;while (end >= start) {int middle = start + (end - start) / 2;// 判断在某个区间内,出现的数字个数,比如在0-2区间,如果出现了4个数字,那么肯定是出现了重复数字了int countByRange = countRange(nums, len, start, middle);// 求到了最后,指针指向了同一个位置if (start == end) {if (countByRange > 1) return start;else break;}// 缩小区间,如果前面区间满足条件,end前移,如果前面不满足条件,start后移if (countByRange > (middle - start + 1)) end = middle;else start = middle + 1;}return -1;}// 查找start 到 end 这个区间内,数组中出现的数字一共有多少个?private int countRange(int[] nums, int len, int start, int end) {int count = 0;for (int i = 0; i < len; i++) {if (nums[i] >= start && nums[i] <= end)++count;}return count;}public static void main(String[] args) {FindDuplicateElementsByBinarySearch f = new FindDuplicateElementsByBinarySearch();int nums[] = {2, 3, 1, 0, 2, 5, 3};int ans = f.getDuplicate(nums);System.out.println((ans == -1) ? "没有重复数字" : "其中重复数字是" + ans);}
}

 

这篇关于剑指offer03-寻找一维数组中重复的数字的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/754502

相关文章

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

Oracle数据库使用 listagg去重删除重复数据的方法汇总

《Oracle数据库使用listagg去重删除重复数据的方法汇总》文章介绍了在Oracle数据库中使用LISTAGG和XMLAGG函数进行字符串聚合并去重的方法,包括去重聚合、使用XML解析和CLO... 目录案例表第一种:使用wm_concat() + distinct去重聚合第二种:使用listagg,

MySQL中删除重复数据SQL的三种写法

《MySQL中删除重复数据SQL的三种写法》:本文主要介绍MySQL中删除重复数据SQL的三种写法,文中通过代码示例讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下... 目录方法一:使用 left join + 子查询删除重复数据(推荐)方法二:创建临时表(需分多步执行,逻辑清晰,但会

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

从去中心化到智能化:Web3如何与AI共同塑造数字生态

在数字时代的演进中,Web3和人工智能(AI)正成为塑造未来互联网的两大核心力量。Web3的去中心化理念与AI的智能化技术,正相互交织,共同推动数字生态的变革。本文将探讨Web3与AI的融合如何改变数字世界,并展望这一新兴组合如何重塑我们的在线体验。 Web3的去中心化愿景 Web3代表了互联网的第三代发展,它基于去中心化的区块链技术,旨在创建一个开放、透明且用户主导的数字生态。不同于传统

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

poj2406(连续重复子串)

题意:判断串s是不是str^n,求str的最大长度。 解题思路:kmp可解,后缀数组的倍增算法超时。next[i]表示在第i位匹配失败后,自动跳转到next[i],所以1到next[n]这个串 等于 n-next[n]+1到n这个串。 代码如下; #include<iostream>#include<algorithm>#include<stdio.h>#include<math.

poj3261(可重复k次的最长子串)

题意:可重复k次的最长子串 解题思路:求所有区间[x,x+k-1]中的最小值的最大值。求sa时间复杂度Nlog(N),求最值时间复杂度N*N,但实际复杂度很低。题目数据也比较水,不然估计过不了。 代码入下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring

usaco 1.2 Name That Number(数字字母转化)

巧妙的利用code[b[0]-'A'] 将字符ABC...Z转换为数字 需要注意的是重新开一个数组 c [ ] 存储字符串 应人为的在末尾附上 ‘ \ 0 ’ 详见代码: /*ID: who jayLANG: C++TASK: namenum*/#include<stdio.h>#include<string.h>int main(){FILE *fin = fopen (