题目描述
解题思路
方法一:
每次移动一位,将整个数组连续移动
M
M
M次,时间复杂度为
O
(
M
∗
N
)
O(M*N)
O(M∗N)。
方法二:
根据移动位数将数组划分为
M
M
M组数据,对每组数据内部移位1次,最后再按原数组顺序将其整合为一个数组。
时间复杂度为
O
(
N
)
O(N)
O(N)。
该方法的缺点在于需要重新申请一个数组空间,空间复杂度非
O
(
1
)
O(1)
O(1)。
方法三:原地算法
由于当移位数
M
>
N
M>N
M>N时,可用
M
%
N
M\%N
M%N的结果当作新的移位数,因此在此仅考虑
M
<
N
M<N
M<N的情况即可。由于左移划分较右移表示形式简单,故在此讨论左移的情况。
显然数组根据移位数
M
M
M将被分为两部分:
A
1
[
0
:
M
]
,
A
2
[
M
:
N
−
1
]
A_1[0: M],A_2[M: N-1]
A1[0:M],A2[M:N−1],对原数组
[
A
1
A
2
]
[A_1A_2]
[A1A2]进行移位操作后将变为
[
A
2
A
1
]
[A_2A_1]
[A2A1],即
[
A
1
T
A
2
T
]
T
[A_1^{T}A_2^{T}]^{T}
[A1TA2T]T,因此对
[
A
1
]
[A_1]
[A1],
[
A
2
]
[A_2]
[A2]及
[
A
1
T
A
2
T
]
[A_1^{T}A_2^{T}]
[A1TA2T]分别进行倒置即可。
数组的倒置只需将
i
i
i从首,
j
j
j从尾开始,对
A
[
i
]
A[i]
A[i]和
A
[
j
]
A[j]
A[j]进行交换,并分别向中间移动至相遇即可。
时间复杂度为
O
(
N
)
O(N)
O(N),空间复杂度为
O
(
1
)
O(1)
O(1)。
算法实现
原地算法代码如下:
//数组倒置
void reverse(int A[], int i, int j)
{
int temp;
for( ;i < j; i++, j--){
temp = A[i];
A[i] = A[j];
A[j] = temp;
}
}
注:
- 注意由于可能存在 M > N M>N M>N的情况,因此应将 M M M调整为 M % N M\%N M%N;
- 左移与右移情况对数组的划分不同:左移时为 M M M和 N − M N-M N−M,右移时为 N − M N-M N−M和 M M M。
参考资料
[1]. PAT B1008题
[2]. 数组(字符数组)原地循环移位