已排好序的整形数组的整合

本文提供了一种在不使用额外空间(O(1)空间复杂度)的情况下,将一个已分为前后两部分且各自有序的整数数组进行排序的方法。通过巧妙地交换元素位置,实现了整个数组的有序排列。

例如已知数组a前半部分a[0,mid - 1],后半部分a[mid,num-1],现前半部分和后半部分均已排好序。

要求:实现a数组的从小到大排序。空间复杂度为O(1).(百度笔试)

[cpp]  view plain copy
  1. #include <stdio.h>  
  2.   
  3. void MergeIntData(int *a, const unsigned int num, const unsigned int mid)  
  4. {  
  5.     if(mid < 0 || num < 0 || NULL == a || a[mid - 1] <= a[ mid ])  
  6.         return;  
  7.   
  8.     unsigned int i,temp, low = 0, high = 0;  
  9.       
  10.     if(mid <= num / 2)  
  11.     {  
  12.         while(low < mid)  
  13.         {     
  14.             while(a[low] < a[mid + high])//不能加等号,否则如果有连续相等在一起的数据,会出现错误  
  15.             {  
  16.                 ++ low;               
  17.             }             
  18.   
  19.             while(a[mid + high + 1] < a[low])  
  20.             {  
  21.                 ++ high;  
  22.   
  23.                 if(high  >= num - mid)  
  24.                 {  
  25.                     high = num - mid - 1;  
  26.                     break;  
  27.                 }  
  28.             }  
  29.   
  30.             temp = a[low];            
  31.             for(i = low; i < mid + high; ++ i)  
  32.             {  
  33.                 a[i] =  a[i + 1];  
  34.             }  
  35.             a[mid + high] = temp;  
  36.         }     
  37.     }  
  38.     else  
  39.     {  
  40.         while(high < num - mid)  
  41.         {     
  42.             while(a[low] < a[mid + high])  
  43.             {  
  44.                 ++ low;               
  45.             }             
  46.   
  47.             temp = a[mid + high];             
  48.             for(i = mid + high; i > low; -- i)  
  49.             {  
  50.                 a[i] =  a[i - 1];  
  51.             }  
  52.             a[low] = temp;  
  53.   
  54.             ++ high;  
  55.         }     
  56.     }  
  57. }  
  58.   
  59.   
  60. int main()  
  61. {  
  62.   
  63. //  int a[] = {0,2,4,6,8,9,10,11,12,14,16,18,1,3,5,7};  
  64. //  int a[] = {0,2,4,6,8,8,9,9,1000,1,3,5,7,10,11,12,14,16,18,20,21,23,25,45,68};  
  65. //  int a[] = {100,1,3,5,7,10,11,12,14,16,18,20,21,23,25,45,68};  
  66. //  int a[] = {8,8,8,9,9,1,5,8,9,10,12,13,14};  
  67. //  int a[] = {1,2,3,4,5,6,7,8,9,2,4,5,7,8,9,10};  
  68. //  int a[] = {0,1,2,3,4,5,6,7,8,9,9,17,100,5,5,5,5,9,10,10000};  
  69.   
  70.     int a[] = {1,2,3,4,5,6,7,100,1000,2,3,5,6,8,1001};  
  71.     int len = sizeof(a) / sizeof(int);  
  72.     int mid =  9;  
  73.   
  74.     MergeIntData(a, len, mid);  
  75.   
  76.     for(int i = 0; i < len; ++ i)  
  77.     {  
  78.         printf("%d  ", a[i]);  
  79.     }  
  80.   
  81.     printf("\n");  
  82.     return 0;  
  83. }  
### C语言中对已排数组的操作 #### 对已排数组进行二分查找 对于已经排好数组,可以高效地使用二分查找算法来定位特定元素的位置。该方法通过反复将待查列折半并比较中间值来进行快速检索。 ```c int binary_search(int sorted_arr[], int target, int low, int high) { while (low <= high) { int mid = low + (high - low) / 2; if (sorted_arr[mid] == target) return mid; if (sorted_arr[mid] < target) low = mid + 1; else high = mid - 1; } return -1; // 如果找不到目标,则返回-1表示未找到 } ``` 此函接受一个整型参`target`作为要寻找的目标值以及两个边界索引`low`和`high`用于限定当前搜索区间[^1]。 #### 合并与去重操作 如果存在多个已排数组需要合并成一个新的有列表,并去除重复项,可以通过如下方式实现: ```c void merge_and_deduplicate(int arr1[], int size1, int arr2[], int size2, int result[]) { int i = 0, j = 0, k = 0; bool isDuplicate; while (i < size1 && j < size2) { if (arr1[i] < arr2[j]) result[k++] = arr1[i++]; else if (arr1[i] > arr2[j]) result[k++] = arr2[j++]; else { result[k++] = arr1[i++]; // 只需加入一次即可 ++j; } // 去除连续相同的元素 isDuplicate = true; while ((isDuplicate ? arr1[i] : arr2[j]) == result[k - 1]) { if (++i >= size1 || ++j >= size2) break; isDuplicate = !isDuplicate; } } // 将剩余部分复制到结果集中 for (; i < size1; ) result[k++] = arr1[i++]; for (; j < size2; ) result[k++] = arr2[j++]; } ``` 这段代码展示了如何有效地处理两个升排列好的整形数组之间的交集运算,同时保证最终得到的结果也是严格递增且不含任何冗余副本的形式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值