287. 寻找重复数

这题的难点就在于下面的说明了,我们先不管下面的那些说明的要求,用常规的解法来解答下上的题目。

排序思想解法

先把原来的数组进行排序,然后逐个遍历,一旦发现后一个元素和当前的元素相等,那么就返回,这就是我们找到了重复数字。但是这种思想,就不满足说明里面的,不能改变原数组,虽然时间复杂度是满足O(n^2)。

哈希思想

用个哈希集合(HashSet)来记录已经出现过的元素,一旦遍历到了元素曾经出现在集合当中,那么就返回,这就是需要寻找的重复数字。

重新排序的思想

这种思想说起来有点复杂,但是时间复杂度是最好的。

我们从头开始遍历数组,遍历到的下标为i,那么我们就分两种情况来讨论:

  1. 如果num[i]等于(i+1),就是值等于刚好等于下标那么就遍历到下一个。因为刚刚好这个就是对应的,我们就不管他了。
  2. 如果num[i]和(i+1)不等,那么就去吧下标等于(num[i] - 1)的数字和这个数字进行交换(下标为i),这样再去判断如今的这个位置上的value和index是否相等,如果不等,继续交换。交换到这个位置上的num[i]和(i+1)相等为止;或者你会找到一个数字,这个数字,那个数字在对应的位置上已经有了,那么这个就是重复的那个数字了。

Talk is cheap, show me the code.

public int findDuplicate(int[] nums) {
if (nums.length == 0) {
return 0;
}
int res = 0;
for (int i = 0, len = nums.length; i < len; i++) {
int temp = i + 1;
// 判断num[i]的值是不是就是放在这
if (temp == nums[i]) {
continue;
} else {
// 两个不相同就进入循环,
while (temp != nums [i]) {
int newIndex = nums[i] - 1;
// 如果位置上的数字和num[i]相等,那么就表示出现重复的数字,
if (nums[newIndex] == nums[i]) {
return nums[i];
}
// 交换两个元素
int swapTemp = nums[newIndex];
nums[newIndex] = nums[i];
nums[i] = swapTemp;
}
}
}
return res;
}

当然了,以上依然不是最好的解法。因为虽然时间是O(n),但是却把原来的数组变动了。

用二分思想

这里的思想有点复杂,大概的思想是这样:

我们先假设一个如果排序好的数组中,你如果取中间的数字,那么如果你的这个中间数 是要比当前的索引的坐标大的话,那么就是也就是nums[i] > i,那么就是说明那个重复的数字是在后半部分的,因为只有在后半部分有重复数字存在的时候,才会多出一个数字来,那么我们就用二分法,吧start取到中点位置,继续寻找;反之,那个重复的数字是在前半部的。

因为我们这数组是没排序的数组,那么我们根据上面的那个计数的思想,我们先取一个取值范围,如果数组里面的元素的取值在这个取值范围的元素个数,等于这个取值范围的区间,那么就表示这个取值范围内不存在重复元素,我们要取别的区间的,继续计数。

public int findDuplicateNew(int[] nums) {
int start = 1;
int end = nums.length;
while (start <= end) {
// 取中值
int middle = start + ((end - start) >> 1);
// 计算从开始值到中值区间内有多少数字。
int tempCount = countRange(nums, start, middle);
// 如果已经区间已经缩小的到了只有一个数了,那么就可以判断在区间内的数字是不是有两个了。
if (start == end) {
if (tempCount > 1) {
return start;
} else {
break;
}
} // 区间就是 中值- 开始值 + 1。然后开始和计数比较。
int range = middle - start + 1;
if (tempCount > range) {
end = middle;
} else if (tempCount <= range) {
start = middle + 1;
}
}
return -1;
} // 计数比较,时间复杂度为O(n)
private int countRange(int[] nums, int start, int end) {
int count = 0;
for (int item : nums) {
if (item >= start && item <= end ) {
count++;
}
}
return count;
}

以上的时间复杂度是$O(NlogN)$ ,二分的时间复杂度是$O(logN)$,每次计数的时间复杂度是$O(N)$。

287. 寻找重复数 Java解法的更多相关文章

  1. leetcode.数组.287寻找重复数-Java

    1. 具体题目 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 1: ...

  2. Java实现 LeetCode 287 寻找重复数

    287. 寻找重复数 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 ...

  3. Leetcode之二分法专题-287. 寻找重复数(Find the Duplicate Number)

    Leetcode之二分法专题-287. 寻找重复数(Find the Duplicate Number) 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和  ...

  4. 【Leetcode】287. 寻找重复数(数组模拟链表的快慢指针法)

    寻找重复数 根据题意,数组中的数字都在1~n之间,所以数字的范围是小于数组的范围的,数组的元素可以和数组的索引相联系. 例如:nums[0] = 1 即可以将nums[0]作为索引 通过nums[0] ...

  5. leetcode 287寻找重复数

    这道题用STL容器就很好写了,可以用set也可以用map, 用unordered_map的C++代码如下: class Solution { public: int findDuplicate(vec ...

  6. Leetcode题目287.寻找重复数(中等)

    题目描述: 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 1: 输入 ...

  7. 【leetcode】287. 寻找重复数

    题目链接:传送门 题目描述: 给定一个数组 nums 包含 n + 1 个整数,每个整数在 1 到 n 之间,包括 1 和 n.现在假设数组中存在一个重复的数字,找到该重复的数字. 注意 不能修改数组 ...

  8. LeetCode | 287. 寻找重复数

    特别感谢LeetCode大佬陈牧远的科普知识 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找 ...

  9. [LeetCode]287. 寻找重复数(二分)

    题目 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 1: 输入: [ ...

随机推荐

  1. 深入理解ES6 - var-let-const

    知识点 var 声明变量: 1.存在变量提升,实际上var无论在哪里声明,都会被当做当前的作用域顶部声明变量. 2.可以重复声明,后声明的变量会覆盖前声明的变量. let 声明变量: 1.不存在变量提 ...

  2. .NET Core 3.0之深入源码理解Kestrel的集成与应用(一)

      写在前面 ASP.NET Core 的 Web 服务器默认采用Kestrel,这是一个基于libuv(一个跨平台的基于Node.js异步I/O库)的跨平台.轻量级的Web服务器. 在开始之前,先回 ...

  3. 08、MySQL—字符串型

    字符串型 1.Char 定长字符:指定长度之后,系统一定会分配指定的空间用于存储数据 基本语法: char(L),L代表字符数(中文与英文字母一样),L长度为0到255 2.Varchar 变长字符: ...

  4. springboot+redis+Interceptor+自定义annotation实现接口自动幂等

    前言: 在实际的开发项目中,一个对外暴露的接口往往会面临很多次请求,我们来解释一下幂等的概念:任意多次执行所产生的影响均与一次执行的影响相同.按照这个含义,最终的含义就是 对数据库的影响只能是一次性的 ...

  5. 西安7月21日「拥抱开源,又见.NET:壹周年Party」线下交流活动

    本次活动既是.NET西安社区的第四次线下交流活动,也是.NET西安社区成立一周年庆活动..NET西安社区2018年7月20日成立,经过一年时间的发展,社区共举办过3次大型线下交流活动,社区人数由最初的 ...

  6. asp.net core系列 67 Web压力测试工具WCAT

    一.介绍 最近搭建了一套CQRS框架,需要在投入开发前,进行必要的压力测试.Web Capacity Analysis Tool  (Wcat)是一种轻量级HTTP负载生成工具,主要用于衡量受控环境中 ...

  7. 在FPS游戏中,玩家对音画同步感知的量化与评估

    前言 在游戏测试中,音画同步测试是个难点(所谓游戏音画同步:游戏中,音效与画面的同步程度),现在一般采用人工主观判断的方式测试,但这会带来2个问题: 无法准确量化,针对同一场景的多次测试结果可能会相反 ...

  8. Java 垃圾收集总结

    概述 垃圾收集(Garbage Collection,GC),它不是Java语言的伴生产物,它的历史比Java还要久远. 人们主要思考GC需要完成的3件事情: 哪些内存需要回收? 什么时候回收? 如何 ...

  9. 对scanner.close方法的误解以及无法补救的错误

    scanner错误关闭导致的异常 public class test2 { public static void main(String[] args) { Scanner scanner1 = ne ...

  10. 堡垒机-jumpserver

    目录 官方网站 Jumpserver 软件包环境要求: 环境 手动本地jumpserver-服务端搭建 初始化一些系统环境设置: 安装相关软件 安装 组件 自建服务器极速安装步骤 0. 防火墙.Sel ...