n元一维向量向左循环移位i的几种算法
1、最简单的算法借助于一个n元的中间向量在n步时间内完成
时间复杂度:O(n) 空间复杂度O(n)
1 void shift_easy(int arr[], int _arr[], int n, int i){ 2 int j = 0; 3 4 while(i < n){ 5 _arr[j++] = arr[i++]; 6 } 7 i = 0; 8 while(j < n){ 9 _arr[j++] = arr[i++]; 10 } 11 12 }
2、使用翻转的思路完成一个不需要额外空间、编写简单并且实际运行很快的算法
时间复杂度:O(n)
1 void swap(int arr[], int i, int j){ 2 int temp; 3 temp = arr[i]; 4 arr[i] = arr[j]; 5 arr[j] = temp; 6 } 7 8 void reverse_shift(int arr[], int n, int i){ 9 int j , k; 10 11 j = 0; 12 while(j < (i - j - 1)){ 13 swap(arr, j, i- j- 1); 14 j++; 15 } 16 j = i; 17 k = 0; 18 while(j < (n - k - 1)){ 19 swap(arr, j, n - k -1); 20 j++; 21 k++; 22 } 23 j=0; 24 while(j < (n - j - 1)){ 25 swap(arr, j, n - j -1); 26 j++; 27 } 28 }
3、在O(n)时间内完成、不需要额外空间的杂技算法
原理是:将x[0]移动到t,将x[i]移动到x[0],将x[2i]移动到x[i](将x的下标对n取模),直到返回取x[0]中的元素,此时改为从t取值并停止过程。如果该过程没有移动全部元素,就从x[1]开始再次移动,直到所有的元素都移动为止。
1 int gcd(int a, int b){ 2 int temp; 3 if(b == 0) 4 return a; 5 do{ 6 temp = a % b; 7 a = b; 8 b = temp; 9 }while(b != 0); 10 return a; 11 } 12 13 void acrob_shift(int arr[], int n, int rotdist){ 14 int j, k, i, temp; 15 16 for(i = 0; i < gcd(rotdist, n); i++){ 17 temp = arr[i]; 18 j = i; 19 while(1){ 20 k = j + rotdist; 21 if(k >= n) 22 k -= n; 23 if(k == i) 24 break; 25 arr[j] = arr[k]; 26 j = k; 27 } 28 arr[j] = temp; 29 } 30 }
4、块交换算法(效率最高)
1 void swap_block(int arr[], int sp1, int sp2, int s){ 2 int temp; 3 while(s > 0){ 4 temp = arr[sp1 + s -1]; 5 arr[sp1 + s - 1] = arr[sp2 + s - 1]; 6 arr[sp2 + s - 1] = temp; 7 s--; 8 } 9 } 10 11 void block_shift(int arr[], int n, int rotdist){ 12 int i, j, p; 13 if(rotdist == 0 || rotdist == n) 14 return; 15 i = p = rotdist; 16 j = n - p; 17 while(i != j){ 18 if(i > j){ 19 swap_block(arr, p-i, p, j); 20 i -= j; 21 } 22 else{ 23 swap_block(arr, p-i, p+j-i, i); 24 j -= i; 25 } 26 } 27 swap_block(arr, p-i, p, i); 28 }