剑指Offer:找出数组中重复的数字

题目: 在一个长度为n的数组里的所有数字都在 0 ~ (n-1)的范围内。数组中 某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为 7 的数组{2,3,1,0,2,5,3},那么对应输出重复 的数字为 2 或者 3 。

思路一:看到这道题,我的思路是先将这个数组进行排序。排序完毕后,遍历数组,如果出现两个相邻的数字相等,那么这个数字就是重复的。代码如下

#include <stdio.h>

int Find(int* arr, int sz)
{
  int i = 0;

  for(i = 0; i < sz; ++i) {
    int j = 0;
    for(j = i; j < sz - 1; ++j) {
      if(arr[j] == arr[j+1]) {
        return arr[j];
      }
    }
  }
  return -1;
}

void swap(int* a, int* b)
{
  *a ^= *b;
  *b ^= *a;
  *a ^= *b;
}


int main()
{
  int arr[] = {2,3,1,0,2,5,3};
  int sz = sizeof(arr)/sizeof(arr[0]); 
  int i = 0;

  for(; i < sz; ++i) {
    int j = 0;
    for(j = i; j < sz - 1; ++j) {
      if(arr[j] > arr[j+1]) {
        swap(&arr[j], &arr[j+1]);
      }
    }
  }
  int ret = Find(arr, sz);
  printf("ret expected 2 or 3, ret actual %d\n",ret);

  return 0;
}

这里写图片描述

思路二:由于这个数组内的元素是由0~(N-1)组成,所以可以利用角标与元素一一对应的关系,来寻找那个相同的元素。
这里写图片描述

#include <stdio.h> 

int FindSameArr(int arr[], int size)
{
  if(arr == NULL) {
    return -1;
  }

  int i = 0;
  for(; i < size; ++i) {
    int tmp = arr[i];
    while(arr[i] != i) {
      if(arr[i] == arr[tmp]) {
        return arr[i];
      }
      arr[i] = arr[tmp];
      arr[tmp] = tmp;
    }
  }
  return -1;
}

int main()
{
  int arr[] = {2,3,1,0,2,5,3};
  int size = sizeof(arr)/sizeof(arr[0]);

  int ret = FindSameArr(arr, size);
  printf("expect ret 3 or 2,actual ret %d\n",ret);

  return 0;
}

这里写图片描述

这样的话,这个代码的时间复杂度就为O(N)。并且相比思路一其效率也较高。


欢迎大家共同讨论,如有错误及时联系作者指出,并改正。谢谢大家!

猜你喜欢

转载自blog.csdn.net/liuchenxia8/article/details/80138365