数组中任意一个重复的数
1-题目描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。
例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
思路
1.交换
0~n-1正常的排序应该是A[i]=i;因此可以通过交换的方式,将它们都各自放回属于自己的位置;
从头到尾扫描数组A,当扫描到下标为i的数字m时,首先比较这个数字m是不是等于i,
如果是,则继续扫描下一个数字;
如果不是,则判断它和A[m]是否相等,如果是,则找到了第一个重复的数字(在下标为i和m的位置都出现了m);如果不是,则把A[i]和A[m]交换,即把m放回属于它的位置;
重复上述过程,直至找到一个重复的数字;
时间复杂度:O(n),空间复杂度:O(1)—所有的操作步骤都是在输入数组上进行的,不需要额外分配空间
(将每个数字放到属于自己的位置最多交换两次)
public class Solution {
public boolean duplicate(int numbers[],int length,int [] duplication) {
if(numbers==null||numbers.length<=0){
duplication[0]=-1;
return false;
}
for(int i=0;i<length;i++){
if(numbers[i]<0||numbers[i]>length-1){
duplication[0]=-1;
return false;
}
}
for(int j=0;j<length;j++){
while(numbers[j]!=j){
if(numbers[j]==numbers[numbers[j]]){
duplication[0]=numbers[j];
return true;
}else{
int temp=numbers[j];
numbers[j]=numbers[temp];
numbers[temp]=temp;
}
}
}
duplication[0]=-1;
return false;
}
}
2.不需要额外的数组或者hash table来保存,题目里写了数组里数字的范围保证在0 ~ n-1 之间,所以可以利用现有数组设置标志,当一个数字被访问过后,可以设置对应位上的数 + n,之后再遇到相同的数时,会发现对应位上的数已经大于等于n了,那么直接返回这个数即可。
时间复杂度:O(n),空间复杂度:O(1)
bool duplicate(int numbers[], int length, int []duplication) {
for (int i = 0; i < length; ++i)
{
int index=numbers[i];
if(index>=length)
index-=length;
if(numbers[index]>=length)
{
duplication[0]=index;
return true;
}
numbers[index]=numbers[index]+length;
}
duplication[0]=-1;
return false;
}
2-题目描述(不修改数组)
在一个长度为n+1的数组里的所有数字都在1到n的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。
也不知道每个数字重复几次。请找出数组中任意一个重复的数字,但不能修改输入的数组。 例如,如果输入长度为8的数组{2,3,5,4,3,2,6,7}, 那么对应的输出重复的数字2或者3。
思路
我们把从 1~n的数字从中间的数字m分为两部分, 后面半为m+1~n。
如果1~m的数字的数目超过m,那么这一半的区间里一定包含重复的数字:
否则,另一半m+1~n的区间里定包含重复的数字。我们可以继续把包含重复数字的区间一分为二, 直到找到一个重复的
数目。
二分法
public static boolean duplicate(int numbers[],int length,int [] duplication) {
if(numbers==null||numbers.length<=0){
duplication[0]=-1;
return false;
}
for(int i=0;i<length;i++){
if(numbers[i]<1||numbers[i]>length-1){
duplication[0]=-1;
return false;
}
}
int low=1;
int high=length-1;
while(low<=high){
int mid=(high+low)/2;
int count=CountRange(numbers,length,low,mid);
if(low==high){
if(count>1){
duplication[0]=low;
return true;
}else{
break;
}
}else{
if(count>mid-low+1){
high=mid;
}else{
low=mid+1;
}
}
}
duplication[0]=-1;
return false;
}
public static int CountRange(int numbers[],int length,int min,int max) {
int count=0;
for(int i=0;i<length;i++){
if(numbers[i]>=min&&numbers[i]<=max){
count++;
}
}
return count;
}
数组中所有重复的数及次数
1-题目描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中所有重复的数字及其次数。
例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出2,2。前面是重复元素,后边是次数
思路
import java.util.HashMap;
import java.util.Set;
public class Solution {
public static void duplicate(int numbers[],int length,int [] duplication) {
if(numbers==null||numbers.length<=0){
duplication[0]=-1;
}
for(int i=0;i<numbers.length;i++){
if(numbers[i]<0||numbers[i]>=numbers.length){
duplication[0]=-1;
}
}
HashMap <Integer, Integer>map = new HashMap<Integer, Integer>();
//hash映射
for (int i = 0; i < length; i++) {
if (map.containsKey(numbers[i])) {
int temp = map.get(numbers[i]);
map.put(numbers[i], ++temp);
} else
map.put(numbers[i], 1);
}
//找到第一个重复的 return
Set<Integer> set = map.keySet();
for(int i : set) {
if (map.get(i) >= 2 ) {
duplication[i] = i;
System.out.print("重复数字:"+i);
System.out.print("重复次数:"+map.get(i));
System.out.println("");
}
}
}
题目2----检查链表是否有环
环检测算法(Floyd’s Tortoise and Hare)
-
分析:当兔子和乌龟在环形跑道上跑步时,在某一时刻,兔子会追上乌龟
-
两个步骤,第一个步骤是确定链表是否有环(也就是重复的数字),第二个步骤是确定环的入口点(重复的数字)在哪里。
1.首先,我们初始化两个指针,一个快速的 hare 指针,一个慢的Tortoise 指针。让hare 一次走两个节点,Tortoise 一个节点。最终,Tortoise 和hare 总会在相同的节点相遇,这样就可以证明是否有环。
2.我们初始化两个指针:ptr1指向列表头部的指针,指向ptr2交叉点的指针 。然后,我们把他们每个每次前进1个节点,直到他们相遇; 他们相遇的节点是环的入口,我们就可以得出结果。 -
时间复杂度O(n)空间复杂度O(1)
public int findDuplicate(int[] nums) {
// Find the intersection point of the two runners.
int tortoise = nums[0];
int hare = nums[0];
do {
tortoise = nums[tortoise];
hare = nums[nums[hare]];
} while (tortoise != hare);
// Find the "entrance" to the cycle.
int ptr1 = nums[0];
int ptr2 = tortoise;
while (ptr1 != ptr2) {
ptr1 = nums[ptr1];
ptr2 = nums[ptr2];
}
return ptr1;
}