c++ 使用二进制排序查找旋转排序数组中的键索引?

avkwfej4  于 2023-06-25  发布在  其他
关注(0)|答案(2)|浏览(145)

这里在这段代码中我面临的问题是关于我的输出找到正确的索引的键。pivot元素的输出是正确的,但我无法在代码的关键索引部分找到错误。能帮我调试一下吗,或者至少告诉我哪里做错了。
这是一个代码,我试图找到一个排序旋转数组中的关键元素的索引,我的方法如下首先我必须找到枢轴元素比我比较枢轴索引处的元素的大小和关键元素的大小,如果大小大于枢轴而小于数组的大小,则在枢轴和(n-1)之间进行二分搜索:数组的最后一个索引并且如果大小小于i,则在第0个索引和枢轴索引之间搜索。
请纠正我的错误。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int getPivot ( int arr[] , int size){
  4. int start =0;
  5. int end = size-1;
  6. int mid = start + ( end - start)/2;
  7. while( start < end ){
  8. if( arr[mid] > arr[0]){
  9. start = mid +1;
  10. }
  11. else{
  12. end = mid;
  13. }
  14. mid = start + ( end - start )/2;
  15. }
  16. return end;
  17. }
  18. int binarySearch ( int arr[] , int size , int s , int e , int key){
  19. int start = s;
  20. int end = e;
  21. int mid = s+( e-s )/2;
  22. while ( start <= end ){
  23. if( arr[mid] == key){
  24. return mid;
  25. }
  26. else if ( arr[mid] > key ){
  27. end = mid -1;
  28. }
  29. else{
  30. start = mid +1;
  31. }
  32. mid = start+( end - start )/2;
  33. }
  34. return start ;
  35. }
  36. int main(){
  37. int n,k;
  38. cin>>n>>k;
  39. int arr[n];
  40. for( int i=0; i<n; i++){
  41. cin>>arr[i];
  42. }
  43. int pivot = getPivot( arr , n);
  44. cout<<" the index of Pivot element is : "<<pivot<<endl;
  45. if( k >= arr[pivot] && k<= arr[n-1] ){
  46. cout<<" the index of the key is : " <<binarySearch( arr , n , pivot , ( n-1) , k)<<endl;
  47. }
  48. else{
  49. cout<<" the index of the key is : " <<binarySearch( arr , n , 0 , (pivot-1) , k)<<endl;
  50. }
  51. return 0;
  52. }
d8tt03nd

d8tt03nd1#

这看起来很有意思:
int mid = s+( e-s )/2;
它没有正确地使用模算术。将arr[mid]与归一化与未规范化坐标以及如何应用于重新计算二分搜索循环的每次迭代的开始和结束。您希望在“归一化”空间中重新计算startend,但mid需要根据透视索引值进行调整。
int main看起来也很可疑:

  1. if( k >= arr[pivot] && k<= arr[n-1] ){
  2. cout<<" the index of the key is : " <<binarySearch( arr , n , pivot , ( n-1) , k)<<endl;
  3. }
  4. else{
  5. cout<<" the index of the key is : " <<binarySearch( arr , n , 0 , (pivot-1) , k)<<endl;
  6. }

如果我理解正确的话,该算法接受了一个可以旋转的排序数组。其中从stdin读取的输入可以是如下内容:

  1. 10 4 // n = 10, key=4
  2. 9 10 11 12 13 1 2 3 4 5 // the sorted rotated array

所以在上面的例子中,如果key==4,那么我们希望返回8作为索引,因为array[8] == 4
这里是你的代码的一个清理版本。主要变化如下:
1.使用正确的标题包括
1.删除了可变长度数组并替换为std::vector。
1.修正了binarySearch中的bug。此外,e参数实际上并不需要这个修复,所以我删除了它。
1.如果找不到元素,binarySearch将返回-1,而不是start
1.修正了main,以一致的方式调用binarySearch的大小和枢轴索引。不需要有两个版本的调用它。也不需要显式传递结束索引。

  1. getPivot也有一些bug。所以我用类似的模运算修正了这个问题。
  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. int getPivot(int arr[], int size) {
  5. int start = 0;
  6. int end = size - 1;
  7. if (size <= 1)
  8. {
  9. return 0;
  10. }
  11. while (start <= end)
  12. {
  13. int len = end - start + 1;
  14. int prev = (start + size - 1) % size;
  15. int mid = (start + end) / 2;
  16. if (arr[start] < arr[prev])
  17. {
  18. return start;
  19. }
  20. if (arr[start] <= arr[mid])
  21. {
  22. start = mid+1;
  23. }
  24. else
  25. {
  26. end = mid;
  27. }
  28. }
  29. return -1;
  30. }
  31. int binarySearch(int arr[], int size, int pivot, int key) {
  32. int start = 0; // start and end are in the "normalized" index space
  33. int end = size - 1;
  34. while (start <= end) {
  35. int mid = (start + end) / 2;
  36. int actualMid = (pivot + mid) % size; // actualMid is the denomalized conversion of mid using modulo arithmetic
  37. if (arr[actualMid] == key) {
  38. return actualMid;
  39. }
  40. else if (arr[actualMid] > key) {
  41. end = mid - 1; // adjust end in normalized index space
  42. }
  43. else {
  44. start = mid + 1; // adjust start in normalized index space
  45. }
  46. }
  47. return -1;
  48. }
  49. int main() {
  50. int n, k;
  51. cin >> n >> k;
  52. std::vector<int> arr(n);
  53. for (int i = 0; i < n; i++) {
  54. cin >> arr[i];
  55. }
  56. int pivot = getPivot(arr.data(), n);
  57. cout << " the index of Pivot element is : " << pivot << endl;
  58. cout << " the index of the key is : " << binarySearch(arr.data(), n, pivot, k) << endl;
  59. return 0;
  60. }
展开查看全部
fbcarpbf

fbcarpbf2#

Java中使用二进制查找算法在旋转排序数组中检索索引

二叉查找算法伪代码流程:

1.将ans变量初始化为-1。
1.将startIndex设置为0,将endIndex设置为size - 1。
1.计算midIndex作为startIndex和endIndex的平均值。

  1. startIndex小于endIndex时输入循环。
  • 检查midIndex处的元素是否等于key:
  • 如果为true,则将midIndex分配给ans并返回ans。
  • 检查midIndex处的元素是否大于数组的第一个元素,并且键是否在第一个元素和midIndex处的元素的范围内:
  • 如果为true,则将endIndex更新为midIndex - 1。
  • 如果为false,则将startIndex更新为midIndex + 1。
  • 将midIndex重新计算为更新后的startIndex和endIndex的平均值。
  • 重复步骤5到7,直到不再满足while循环中的条件。

9.返回ans的值,如果找到键,则表示键的索引;如果没有找到,则返回-1。

迭代方法

  1. public int findKey(int[] arr, int size, int key){
  2. int ans = -1;
  3. int startIndex = 0;
  4. int endIndex = size - 1;
  5. int midIndex = startIndex + (endIndex - startIndex) / 2;
  6. while (startIndex<=endIndex){
  7. if(arr[midIndex] == key){
  8. ans = midIndex;
  9. return ans;
  10. } else if (arr[midIndex] > arr[0] && (key >= arr[0] && key < arr[midIndex])) {
  11. endIndex = midIndex - 1;
  12. }else {
  13. startIndex = midIndex + 1;
  14. }
  15. midIndex = startIndex + (endIndex - startIndex) / 2;
  16. }
  17. return ans;
  18. }

在此发现全面的解决方案https://github.com/Amir36036/ds/blob/array/src/main/java/org/ds/array/FIndKeyINRotatedSortedArray.java

展开查看全部

相关问题