1、在长度为n的数组中,数组值为范围0-n-1范围内的整数,请找出其中任意一个重复的数字。
取值范围0-n-1
找出其中一个就可以
算法思想:从第一个开始,把数组值放在对应的下标值数组中,比如下标为0的值为5,那么就把5放在下标为0的数组中,这样如果有两个相同的数值就会放在同一个下标下,这样每一个元素最多移动两次就可以找到正确的位置。
public static int duplicateNumber(int arr[]){
if(arr==null||arr.length<1)
return -1;
for(int i=0;i<arr.length;i++){
if(arr[i]<0||arr[i]>arr.length-1){
return -1;
}
}
for(int i=0;i<arr.length;i++){////只有在arr[i]!=i下是找到重复数字与原来同一个位置发生碰撞
while(arr[i]!=i){//所有被交换到i位置的元素都放在了对应的位置 但并不是所有的元素都交换了 但下标为i的值一定是i,或者这一轮找到重复数字
if(arr[i]==arr[arr[i]]){
return arr[i];
}
int temp=arr[i];
arr[i]=arr[temp];
arr[temp]=temp;
}
}
return -1;
}
上面这种情况可以找出其中一个(从最小下标开始找,应该是找到最小的第一个重复值)
2、与1同样的条件,找出所有重复的元素
空间换时间
//花费一个与原数组大小相等的标记数字
public static void findAllDuplicateBySpace(int arr[]){
if(arr==null||arr.length<1){
System.out.println(-1);
return;
}
for(int i=0;i<arr.length;i++){
if(arr[i]<0||arr[i]>=arr.length){
System.out.println(-1);
return;
}
}
int flag[]=new int[arr.length];
for(int i=0;i<arr.length;i++){
flag[arr[i]]++;
}
for(int i=0;i<flag.length;i++){
if(flag[i]>1)
System.out.print(i+" ");
}
}
要节省空间就要花费时间排序
public static void quickSort(int arr[],int low,int high){
int l=low;
int h=high;
int povit=arr[low];
while(l<h){
while(l<h&&arr[h]>=povit)
h--;
if(l<h){
int temp=arr[h];//povit
arr[h]=arr[l];
arr[l]=temp;
l++;
}
while(l<h&&arr[l]<=povit)
l++;
if(l<h){
int temp=arr[l];//povit
arr[l]=arr[h];
arr[h]=temp;
h--;
}
}
if(l>low)quickSort(arr,low,l-1);
if(h<high) quickSort(arr,l+1,high);
}
//时间换空间 先排序
public static void findAllDuplicateByTime(int arr[]){
if(arr==null||arr.length<1){
System.out.println(-1);
return;
}
for(int i=0;i<arr.length;i++){
if(arr[i]<0||arr[i]>=arr.length){
System.out.println(-1);
return;
}
}
quickSort(arr,0,arr.length-1);
System.out.println();
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+" ");
}
System.out.println();
boolean isDuplicate=false;
for(int i=0;i<arr.length-1;i++){
if(arr[i]==arr[i+1]){
if(!isDuplicate)
System.out.print(arr[i]+" ");
isDuplicate=true;
}else{
isDuplicate=false;
}
}
}
3、去除链表中重复元素(重复元素留一个)
public class LinkTable {
Node head=null;
class Node{
Node next;
int value;
public Node(int value){
this.value=value;
}
}
public void removeDuplicateNode(Node head){
if(head==null)
return;
Node p=head;
Node q=head;
while(p.next!=null){
if(p.value==p.next.value){
q=p.next;
p.next=p.next.next;
q.next=null;
}else{
p=p.next;
}
}
p=head;
while(p!=null){
System.out.print(p.value+" ");
p=p.next;
}
}
}
4、重复元素一个不留
public void removeAllDuplicate(Node head){
if(head==null)
return;
Node pPreNode=null;
Node pNode=head;
while(pNode!=null){
Node pNext=pNode.next;
boolean isDuplicate=false;
if(pNext!=null&&pNext.value==pNode.value)
isDuplicate=true;
if(!isDuplicate){
pPreNode=pNode;
pNode=pNode.next;//保证和pNext重合与下面对应
}else{
int delValue=pNode.value;
Node toDelNode=pNode;
while(toDelNode!=null&&toDelNode.value==delValue){
pNext=toDelNode.next;
toDelNode.next=null;
//toDelNode=null;
toDelNode=pNext;
}
//执行到这里 pNext都指向一个新的值节点(可能是重复的节点)pNode指向节点已经被删除了 所以下面需要连接 保证链是连接的
if(pPreNode==null){//代表还没有找到第一个不重复的头节点
head=pNext;
}else{
pPreNode.next=pNext;//pPreNode指向的还是没有重复的节点 要保证链表链不能断 上面会用到 pPreNode指向下一个pNode而不是自己后移 所以需要保证这个链不能断
}
pNode=pNext;///保证和pNext重合
}
}
}