看到这个题目,一般是先实现题目意思再说,一般我们按照正常思路解题,将数组元素循环右移,比如abcd1234,假若循环四位,就是4abcd123->34abd12->234abcd1->1234abcd,这样的话代码很简单:
1
2
3
4
5
6
7
8
|
RightShift(
int
[] arr,
int
N,
int
K){
while
(K--){
int
t = arr[N-
1
];
for
(
int
i = N-
1
;i>
0
; i--){
}
arr[
0
] = t;
}
}
|
这样写是可以实现循环向右移动,但是这样的时间复杂度实O(N * K),是不符合题目要求的。那么还需要别的解法。
我们通过观察看以看到,数组abcd234向右移动K位,相当于向左移动-K位,向右移动跟向左移动本质上是一样的。
在考虑解题的同时,我们应该想到的是K的取值是可以大于N的,不要让惯性思维束缚了我们的大脑,假若K>N,那么数组向右移动4位跟向右移动12位,20,28是等同的,那么我们可以先做一个处理,K=K%N,这样我们的代码就变成了:
1
2
3
4
5
6
7
8
9
|
RightShift(
int
[] arr,
int
N,
int
K){
K=K % N ;
while
(K--){
int
t = arr[N-
1
];
for
(
int
i = N-
1
;i>
0
; i--){
}
arr[
0
] = t;
}
}
|
这样结果的话,运算的时间复杂度变成了O(N * N ),时间复杂度降低了,但是还不符合题目要求;,继续探索
假如abcd234向右移动四位的话,我们可以发现其实是abcd跟1234兑换了一下,把两部分分别看成一个整体,然后兑换,具体步骤如下:
1、abcd倒叙->dcba1234
2、1234倒叙->dcba4321
3、全部倒叙->1234abcd
按照这个思路写代码的话就变成了如下结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
ReghtShift(
int
[] arr,
int
N,
int
K){
K%=N;
Reverse(
int
[] arr,
0
,N-k-
1
);
Reverse(
int
[] arr,N-K,N-
1
);
Reverse(
int
[] arr,
0
,N-
1
);
}
Reverse(
int
[] arr,
int
b,
int
e){
for
(;b<e;b++,e--){
int
temp = arr[e];
arr[e] = arr[b];
arr[b] = temp;
}
}
|
这样的话就可以在线性时间内实现向右移动操作了