Design an algorithm to shift K-bit right of an array containing n elements. The time complexity is O (n) and only two additional variables are allowed.
The solution is as follows:
First, let's try a simple method. We can shift the elements in the array one bit right each time and iterate K times. Abcd1234 ---> 4abcd123 ---> 34abcd12 ---> 234abcd1 ---> 1234 ABCD. The Code is as follows:
[CPP]View plaincopy
- Rightshift (int * arr, int N, int K)
- {
- While (k --)
- {
- Int T = arr [n-1];
- For (INT I = n-1; I> 0; I --)
- {
- Arr [I] = arr [I-1];
- }
- Arr [0] = T;
- }
- }
Although this algorithm can realize the right shift of the array loop, the complexity of the algorithm is O (K * n), which does not meet the requirements of the question. We should continue to explore.
Analysis and Solution
If the array is abcd1234 and the loop shifts four places to the right, the expected status is 1234 ABCD. K is a non-negative integer. When K is a negative integer, K is shifted to the right, which is equivalent to the Left shift (-k). The left shift is essentially the same as the right shift.
Solution 1
In the beginning, we may have such a potential assumption: k <n. In fact, this is also true in many cases. But strictly speaking, we cannot use this "inertial thinking" to think about problems. In programming, it is very important to fully consider the problem. K may be an integer greater than N. At this time, the above solution needs to be improved.
After carefully observing the characteristics of the right shift of the loop, it is not difficult to find that each element will return to its position after shifting N places to the right. Therefore, if k> N, the array sequence after right-shift K-N is the same as the result of right-shift K-bit. Then we can draw a general rule: the case after the right shift of K bit is the same as the case after the right shift of k' = K % N, the Code is as follows:
[CPP]View plaincopy
- 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 [I] = arr [I-1];
- }
- Arr [0] = T;
- }
- }
It can be seen that the complexity of the algorithm is reduced to O (N ^ 2) after the feature of moving the right of the loop is added. This is irrelevant to K and is a step closer to the requirement of the question. However, the time complexity is not low enough. Let's continue to explore the associations between arrays before and after the right shift of the loop.
Solution 2
We still regard the string as a string consisting of two segments, with the XY value. The left rotation is equivalent to converting the string XY into Yx. First, we define a flip operation on the string, that is, the character order in the flip string. After turning X, record it as XT. Obviously (XT) t = x.
We first perform the flip operation on the X and Y segments respectively to obtain the xtyt. Then perform the xtyt flip operation to obtain(Xtyt) t = (yt) T (XT) t = Yx. This is exactly the expected result.
After analysis, we can return to the original question. All we need to do is to divide the string into two segments. The first segment is the first M character, and the remaining characters are divided into the second segment. Define another function to flip the string and follow the previous steps to flip it three times. Both time complexity and space complexity are in line with requirements.
Assume that the original array sequence is abcd1234 and the transformed array sequence is 1234 ABCD, that is, four digits are shifted to the right of the loop. After comparison, it is not difficult to see that there are two segments in the same order: 1234 and ABCD. You can consider these two segments as two parts, the K-bit shift to the right is to exchange the two parts of the array. The conversion process is completed through the following steps:
1. Sort ABCD in reverse order: abcd1234 ---> dcba1234;
2. Sort 1234 in reverse order: dcba1234 ---> dcba4321;
3. All reverse order: dcba4321 ---> 1234 ABCD.
The Code is as follows:
[CPP]View plaincopy
- Reverse (int * arr, int B, int e) // sort in reverse order
- {
- For (; B <E; B ++, e --) // traverse from the front and back of the array
- {
- Int temp = arr [E];
- Arr [e] = arr [B];
- Arr [B] = temp;
- }
- }
- Rightshift (int * arr, int N, int K)
- {
- K = K % N;
- Reverse (ARR, 0, N-K-1); // The Reverse Order of the front N-K Section
- Reverse (ARR, N-K, N-1); // back-to-back K part
- Reverse (ARR, 0, N-1); // All reverse
- }
In this way, we can implement the right shift operation in linear time.