将數組元素向右移動k個位置,k非負
文章目錄
- 第一種方案
- 第二種方案
- 第三種方案
第一種方案
解決思路:将數組中的元素複制到一個新數組中,将數組元素依次配置設定到新的位置上
時間複雜度:O(n)
空間複雜度:O(n)
void rotate(int* nums,int numsSize,int k)
{
k%=numsSize;
int newArray[numsSize];
for(int i=0;i<numsSize;i++)
newArray[i]=nums[i];
for(int j=0;j<numsSize;j++)
nums[(j+k)%numsSize]=newArray[j];
}
第二種方案
解決思路:先反轉所有的數組元素;再反轉前k個數組元素;最後反轉剩餘的數組元素
時間複雜度:O(n)
空間複雜度:O(1)
void swap(int* x,int* y)
{
int temp;
temp=*x;*x=*y;*y=temp;
}
void rotate(int* nums,int numsSize,int k)
{
k%=numsSize;
for(int i=0;i<numsSize/2;i++)
swap(nums+i,nums+numsSize-i-1);
for(int i=0;i<k/2;i++)
swap(nums+i,nums+k-i-1);
for(int i=0;i<(numsSize-k)/2;i++)
swap(nums+k+i,nums+numsSize-i-1);
}
第三種方案
解決思路:利用一個空間儲存數組的第一個元素,計算第一個元素移動後的位置,将該位置上的元素與空間中的元素進行交換,然後繼續計算交換後的元素移動後的位置并重複上述操作
舉一個例子[1,2,3,4,5,6,7],k=3
利用一個空間temp進行元素之間的交換
(1)temp=1 移動到的位置4 替換後temp=4 [1,2,3,1,5,6,7]
(2)temp=4 移動到的位置7 替換後temp=7 [1,2,3,1,5,6,4]
(3)temp=7 移動到的位置3 替換後temp=3 [1,2,7,1,5,6,4]
(4)temp=3 移動到的位置6 替換後temp=6 [1,2,7,1,5,3,4]
(5)temp=6 移動到的位置2 替換後temp=2 [1,6,7,1,5,3,4]
(6)temp=2 移動到的位置5 替換後temp=5 [1,6,7,1,2,3,4]
(7)temp=5 移動到的位置1 替換後temp=1 [5,6,7,1,2,3,4]
但是這樣存在一個隐性的問題,如[1,2,3,4,5,6],k=3
(1)temp=1 移動到的位置4 替換後temp=4 [1,2,3,1,5,6]
(2)temp=4 移動到的位置1 替換後temp=1 [4,2,3,1,5,6]
我們會發現在這種情況下會陷入一個循環(形成了一個圈),在兩個數組元素之間不斷地變換。這時候就需要我們從第二個元素開始再次進行計算。
通過規律我們可以發現,假設數組元素個數為 n n n,形成的圈數為 x x x,形成的圈周遊元素的個數為 y y y,則有 x n = y k xn=yk xn=yk,是以 x n xn xn是 n n n, k k k的公倍數。又因為我們希望經過最少的圈就能回到起點,即算法結束,是以 x x x應該盡可能的小。在這種情況下 x n xn xn應為 n n n和 k k k的最小公倍數,即 x n = l c m ( n , k ) xn=lcm(n,k) xn=lcm(n,k)
x n = l c m ( n , k ) = y k xn=lcm(n,k)=yk xn=lcm(n,k)=yk
y = l c m ( n , k ) / k y=lcm(n,k)/k y=lcm(n,k)/k
一圈我們可以周遊的元素個數為 y y y
是以周遊次數為 n l c m ( n , k ) / k = n k l c m ( n , k ) = g c d ( n , k ) \cfrac{n}{lcm(n,k)/k}=\cfrac{nk}{lcm(n,k)}=gcd(n,k) lcm(n,k)/kn=lcm(n,k)nk=gcd(n,k)
是以周遊的次數為 n n n和 k k k的最大公約數
int gcd(int x,int y)
{
return y?gcd(y,x%y):x;
}
void swap(int* x,int* y)
{
int temp;
temp=*x;*x=*y;*y=temp;
}
void rotate(int* nums,int numsSize,int k)
{
k%=numsSize;
int count=gcd(k,numsSize);
for(int i=0;i<count;i++){
int start=i,temp=nums[start];
do{
int next=(start+k)%numsSize;
swap(&temp,nums+next);
start=next;
}while(start!=i);
}
]
時間複雜度:O(n)
空間複雜度:O(1)