287. 寻找重复数 Java解法
287. 寻找重复数

这题的难点就在于下面的说明了,我们先不管下面的那些说明的要求,用常规的解法来解答下上的题目。
排序思想解法
先把原来的数组进行排序,然后逐个遍历,一旦发现后一个元素和当前的元素相等,那么就返回,这就是我们找到了重复数字。但是这种思想,就不满足说明里面的,不能改变原数组,虽然时间复杂度是满足O(n^2)。
哈希思想
用个哈希集合(HashSet)来记录已经出现过的元素,一旦遍历到了元素曾经出现在集合当中,那么就返回,这就是需要寻找的重复数字。
重新排序的思想
这种思想说起来有点复杂,但是时间复杂度是最好的。
我们从头开始遍历数组,遍历到的下标为i,那么我们就分两种情况来讨论:
- 如果num[i]等于(i+1),就是值等于刚好等于下标那么就遍历到下一个。因为刚刚好这个就是对应的,我们就不管他了。
- 如果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解法的更多相关文章
- leetcode.数组.287寻找重复数-Java
1. 具体题目 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 1: ...
- Java实现 LeetCode 287 寻找重复数
287. 寻找重复数 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 ...
- Leetcode之二分法专题-287. 寻找重复数(Find the Duplicate Number)
Leetcode之二分法专题-287. 寻找重复数(Find the Duplicate Number) 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 ...
- 【Leetcode】287. 寻找重复数(数组模拟链表的快慢指针法)
寻找重复数 根据题意,数组中的数字都在1~n之间,所以数字的范围是小于数组的范围的,数组的元素可以和数组的索引相联系. 例如:nums[0] = 1 即可以将nums[0]作为索引 通过nums[0] ...
- leetcode 287寻找重复数
这道题用STL容器就很好写了,可以用set也可以用map, 用unordered_map的C++代码如下: class Solution { public: int findDuplicate(vec ...
- Leetcode题目287.寻找重复数(中等)
题目描述: 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 1: 输入 ...
- 【leetcode】287. 寻找重复数
题目链接:传送门 题目描述: 给定一个数组 nums 包含 n + 1 个整数,每个整数在 1 到 n 之间,包括 1 和 n.现在假设数组中存在一个重复的数字,找到该重复的数字. 注意 不能修改数组 ...
- LeetCode | 287. 寻找重复数
特别感谢LeetCode大佬陈牧远的科普知识 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找 ...
- [LeetCode]287. 寻找重复数(二分)
题目 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 1: 输入: [ ...
随机推荐
- 网络基础与FTP准备
一网络基础 1.端口: 端口是为了将同一台电脑上的不同程序进行隔离 (IP是在找电脑,端口是在找电脑上的程序) 实例: MySQL是一个软件,帮助我们在硬盘上进行操作,默认端口是3306 Redis是 ...
- No.595-Big Countries-(LeetCode之Database篇)
数据库表 给出的数据库表如下,表名为World. +-----–+----+----+----–+-----+ | name | continent | area | ...
- 基于python语言的自动化测试中生成html的测试报告时HtmlTestRunner模块常见问题
一.导入了HTMLTestRunner模块,报错:No module named StringIO,在python3.x中确实没有,在第94行引入的名称改成import io,539行要改成self. ...
- 时间段(今天,昨天,本周,上周,本月,上月,总)的查询,时间处理函数strtotime
需求:最近get了一个很好用的PHP关于时间的函数strtotime,因为最近有个项目涉及到很多时间段(今天,昨天,本周,上周,本月,上月,总)的查询,要根据指定时间算出它每个范围的开始时间和结束时间 ...
- POJ 3183:Stump Removal(模拟)
http://poj.org/problem?id=3183 题意:有n个树桩,分别有一个高度h[i],要用Bomb把树桩都炸掉,如果炸的位置的两边树桩高度小于Bomb炸的树桩高度,那么小于树桩高度的 ...
- Go - 循环
目录 概述 循环 array 循环 slice 循环 map break continue goto switch 推荐阅读 概述 前几篇文章分享了 array 数组.slice 切片.map 集合, ...
- 有意思的 CDN
Clean Clean false 7.8 磅 0 2 false false false EN-US ZH-CN AR-SA /* Style Definitions */ table.MsoNor ...
- find文件删除
find /root/title/test -type f -name '*.txt' -exec rm {} \; 查找并删除test文件夹下所有txt文件 find /root/title/t ...
- springboot之mybatisplus,mp的简单理解
这是一张简单的service的继承图.可以看到我们的执行类,即XxxServiceImpl的继承关系. 从上到下,ServiceImpl和BaseMapper是一个依赖关系,ServiceImpl和I ...
- ElementUI 源码简析——源码结构篇
ElementUI 作为当前运用的最广的 Vue PC 端组件库,很多 Vue 组件库的架构都是参照 ElementUI 做的.作为一个有梦想的前端(咸鱼),当然需要好好学习一番这套比较成熟的架构. ...