I am trying to solve this CodingBat problem:
(This is a slightly harder version of the fix34 problem.) Return an array that contains exactly the same numbers as the given array, but rearranged so that every 4 is immediately followed by a 5. Do not move the 4’s, but every other number may move. The array contains the same number of 4’s and 5’s, and every 4 has a number after it that is not a 4. In this version, 5’s may appear anywhere in the original array.
fix45({5, 4, 9, 4, 9, 5}) → {9, 4, 5, 4, 5, 9} fix45({1, 4, 1, 5}) → {1, 4, 5, 1} fix45({1, 4, 1, 5, 5, 4, 1}) → {1, 4, 5, 1, 1, 4, 5}
I initially used a method which passed all of the sites tests, but I don’t think it would work for longer arrays. The initial method used 2 loops and did not use a new array. I have created a solution which introduces a new array and a 3rd nested loop and I believe will work for all instances of the problem. However, the site states that the problems in this section can be solved with 2 loops, so I am wondering if there actually is a 2 loop solution that will work for anyinstance of the problem. Here is the question and my 3 loop solution:
public int[] fix45(int[] nums) { int[] locations = {-1}; for (int i = 0; i < nums.length - 1; ++i) { if (nums[i] == 4) { JLoop: for (int j = nums.length-1; j >= 0; --j) { if (nums[j] == 5) { for (int k = locations.length-1; k>=0 ; --k) { if (locations[k] == j) { continue JLoop; } } nums[j] = nums[i + 1]; nums[i + 1] = 5; locations[locations.length - 1] = i+1; locations = java.util.Arrays.copyOf(locations, locations.length + 1); locations[locations.length-1] = -1; break; } } } } return nums; }
Advertisement
Answer
Restarting the search for a suitable 5 from one end of the array every time a 4 is found seems wasteful. Part of the array has already been scanned and is known not to contain a 5 that can be moved. This is O(n) time and O(1) space.
public static int[] fix45(int[] nums) { int j = 0; for (int i = 0; i < nums.length - 1; ++i) { if (nums[i] == 4 && nums[i + 1] != 5) { /* * Need to find the next movable 5 That means an element that is 5 and * either is the first element or is preceded by anything other than 4 */ while (nums[j] != 5 || (j != 0 && nums[j - 1] == 4)) { j++; } nums[j] = nums[i + 1]; nums[i + 1] = 5; } } return nums; }