This is from G4G. link
Problem description:
Given an array of size n where all elements are in range from 0 to n-1, change contents of arr[] so that arr[i] = j is changed to arr[j] = i.
Examples:
Example 1:
Input: arr[] = {1, 3, 0, 2};
Output: arr[] = {2, 0, 3, 1};
Explanation for the above output.
Since arr[0] is 1, arr[1] is changed to 0
Since arr[1] is 3, arr[3] is changed to 1
Since arr[2] is 0, arr[0] is changed to 2
Since arr[3] is 2, arr[2] is changed to 3
Example 2:
Input: arr[] = {2, 0, 1, 4, 5, 3};
Output: arr[] = {1, 2, 0, 5, 3, 4};
Example 3:
Input: arr[] = {0, 1, 2, 3};
Output: arr[] = {0, 1, 2, 3};
Example 4:
Input: arr[] = {3, 2, 1, 0};
Output: arr[] = {3, 2, 1, 0};
Analysis:
This is similar to the circle sort. The current position will determine the next position in array. Finally, it will finish by circulate back to the beginning position. In order to reach O(1) space, I changed the value to negative to mark that a position is finished. In the end, restore the initial values in the array.
Code:
- public static void rearrangeArray(int[] a) {
- if (a == null || a.length == 1) {
- return;
- }
- for (int start_pos = 0; start_pos < a.length; start_pos++) {
- if (a[start_pos] < 0) {
- continue;
- }
- int next_pos = a[start_pos];
- int pre_pos = start_pos;
- while (next_pos != start_pos) {
- int tmpNextPos = a[next_pos];
- a[next_pos] = -pre_pos – 1;
- pre_pos = next_pos;
- next_pos = tmpNextPos;
- }
- a[start_pos] = -pre_pos – 1;
- }
- for (int i = 0; i < a.length; i++) {
- a[i] = -(a[i] + 1);
- }
- }