【C/C++练习题】数组中重复的数字

举报
王建峰 发表于 2021/11/19 00:45:09 2021/11/19
【摘要】 《剑指Offer》面试题3   问题一、找出数组中重复的数字    题目:在一个长度为n的数组里的所有数字都在0到n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了, 也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2, 3, 1, 0, 2, ...

《剑指Offer》面试题3

 

问题一、找出数组中重复的数字
  

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

 

分析:数组的长度(n)等于数字的范围(0~n-1),如果使用数组下标来定位数组中数字的话,会出现两种情况

没有重复数字:每一个位置刚好对应一个数字,排序后的数组元素的值和下标一一对应

有重复数字:有些位置可能会出现多个数字,有些位置可能没有数字

 

算法思想:重排数组,把元素放置在指定的位置。通过遍历数组的每一个元素,

如果数组元素的值等于下标值,继续遍历下一个元素
如果数组元素的值不等于下标值,根据元素的值找到对应的位置,进行比较,再根据比较结果判断
    比较值相等,找出重复数字,返回
    比较值不等,进行位置交换
继续判断数组元素的值....

 

其他方法:

1.对数组排序,在已排序的数组中扫描重复数字

2.创建哈希表,通过判断新加入的数字在哈希表中是否已存在,来判断重复数字

 

代码


  
  1. #include "iostream"
  2. using namespace std;
  3. //函数功能:寻找数组中的任意重复数字
  4. //输入参数:numbers[] 源数组、length 数组长度、duplication 重复元素
  5. //返回值: false 没有重复数字、true发现重复数字
  6. bool duplicate(int numbers[], int length, int* duplication)
  7. {
  8. //判断无效参数
  9. if ( (numbers == nullptr) || (length < 0) )
  10. {
  11. return false;
  12. }
  13. //判断元素数是否满足
  14. for (int i = 0; i < length; i++)
  15. {
  16. if ( (numbers[i] < 0) || (numbers[i] > length-1) )
  17. {
  18. return false;
  19. }
  20. }
  21. for (int i = 0; i < length; i++)
  22. {//1.遍历数组
  23. while(i != numbers[i])
  24. {//2.判断当前值是否等于下标值
  25. if (numbers[i] == numbers[numbers[i]])
  26. {//3.判断当前值是否已放置下标位置(判断存在)
  27. *duplication = numbers[i]; //计入重复元素
  28. return true; //4.已存在,返回结果
  29. }
  30. //5.交换当前值到下标位置
  31. int temp = numbers[i];
  32. numbers[i] = numbers[temp];
  33. numbers[temp] = temp;
  34. }
  35. }
  36. return false; //没有找到
  37. }
  38. //进行测试
  39. void test01()
  40. {
  41. int numbers[] = {2, 3, 1, 0, 2, 5, 3};
  42. int duplication = 0;
  43. if ( duplicate(numbers, sizeof(numbers)/sizeof(int), &duplication) == true )
  44. {
  45. cout << "res:" << duplication << endl;
  46. }
  47. }
  48. int main(int argc, char const *argv[])
  49. {
  50. test01();
  51. return 0;
  52. }

运行

 

 

问题二、不修改数组找出重复的数字


题目:在一个长度为n+1的数组里的所有数字都在1到n的范围内,所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但不能修改输入的数组。例如,如果输入长度为8的数组{2, 3, 5, 4, 3, 2, 6, 7},那么对应的输出是重复的数字2或者3。

 

分析:数组长度(n+1)大于数字的范围,所以一定有重复的数字。使用二分法的思路,将不断小查找区间的范围,对重复数字进行查找。

 

其他方法:创建一个辅助数组,在辅助数组中查找重复数字,不会破坏原数组的结构。

 

代码


  
  1. #include "iostream"
  2. using namespace std;
  3. int countRange(const int* numbers, int length, int start, int end); //统计次数
  4. int getDuplication(const int* numbers, int length); //查找任意重复数字
  5. //功能:(已知)数组内有重复数字,查找重复数字
  6. //输入:numbers源数组(数字范围1-n)、length数组长度(n+1)
  7. //返回:重复的数字
  8. int getDuplication(const int* numbers, int length)
  9. {
  10. if ( (numbers == nullptr) || (length <= 0) )
  11. {//无效参数
  12. return -1;
  13. }
  14. int start = 1;
  15. int end = length - 1;
  16. while(start <= end)
  17. {
  18. //1.将数字序列所在区间进行二分
  19. int middle = (end - start)/2 + start;
  20. //2.统计区间范围的数字的出现次数
  21. int count = countRange(numbers, length, start, middle);
  22. //3.判断区间长度是否为1,找出重复数字
  23. if (start == end)
  24. {
  25. if (count > 1)
  26. {
  27. return start;
  28. }
  29. else
  30. {
  31. break;
  32. }
  33. }
  34. //4.重新调整区间,区间内包含重复数字
  35. if ( count > ((middle - start) + 1) )
  36. {
  37. end = middle;
  38. // end = middle - 1;
  39. }
  40. else
  41. {
  42. start = middle + 1;
  43. }
  44. }
  45. return -1;
  46. }
  47. //功能:统计start-end范围的数字的出现次数
  48. //输入:numbers源数组、length数组长度、start,end表示数字范围
  49. int countRange(const int* numbers, int length, int start, int end)
  50. {
  51. if ( (numbers == nullptr) || (length <= 0) )
  52. {//无效参数
  53. return 0;
  54. }
  55. int count = 0;
  56. for (int i = 0; i < length; i++)
  57. {//遍历数组元素
  58. if ( (start <= numbers[i]) && (numbers[i] <= end) )
  59. {
  60. count++; //统计次数
  61. }
  62. }
  63. return count;
  64. }
  65. void test01()
  66. {
  67. int arr[] = {2, 3, 5, 4, 3, 2, 6, 7};
  68. int res = getDuplication(arr, sizeof(arr)/sizeof(int));
  69. cout << "res:" << res << endl;
  70. }
  71. int main(int argc, char const *argv[])
  72. {
  73. test01();
  74. return 0;
  75. }

 

运行

 

 

总结:面试官提出的需求不同,最终所采用的算法也不相同,这说明面试中和面试官的交流的重要性!!

 

我的码云https://gitee.com/hinzer/sword_to_offer/tree/master/questions

文章来源: blog.csdn.net,作者:hinzer,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/feit2417/article/details/96566093

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。