Is there a simpler solution for Codingbat fix45?

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;
    }

Using an extra array, here's a solution with "one loop" (loops without nested loops):

public int[] fix45(int[] nums) {
  int[] otherValues = new int[nums.length];

  for(int i = 0, c = 0; i < nums.length; i++)
    if(nums[i] != 4 && nums[i] != 5)
      otherValues[c++] = nums[i];

  for(int i = 0, c = 0; i < nums.length; i++)
    if(nums[i] == 4)
      nums[++i] = 5;
    else
      nums[i] = otherValues[c++];

  return nums;
}

We fix the fours, take out the non-fours and non-fives, and put the values all back in in order.

To improve the space usage (perhaps not by much), you can count the number of fours before you make the extra array.

Tags:

Algorithm

Java