diff --git a/src/main/java/com/company/problem/hard/SliceSort.java b/src/main/java/com/company/problem/hard/SliceSort.java new file mode 100644 index 0000000..eb6c225 --- /dev/null +++ b/src/main/java/com/company/problem/hard/SliceSort.java @@ -0,0 +1,104 @@ +package com.company.problem.hard; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +/** + * PROBLEM: + * + * We are given an array A consisting of N distinct integers. + * We would like to sort array A into ascending order using a simple algorithm. + * First, we divide it into one or more slices (a slice is a contiguous subarray). + * Then we sort each slice. After that, we join the sorted slices in the same order. + * Write a function solution that returns the maximum number of slices for which the algorithm will return a correctly sorted array. + * + * 1. Given A = [2,4,1,6,5,9,7] will return e. + * [2,4,1], [6,5], [9,7] then after soring each slice and joining them together, the whole array will be sorted into ascending order. + * + * A= [4,3,2,6,1] will return 1. the array cannot be split into smaller slices; it has to be sorted all at once. + * + * + * 3. A = [2,1,6,4,3,7] will return 3. + * + * N range [1..100,000] + * element range [1..1,000,000,000] + */ +public class SliceSort { + + public int sort(Integer[] array) { + int count = 0; + + // 1) Slice until asc order stops (Note: a last element included) + List slices = slice(array); + + // Exit condition: Only a single slice exits + if (slices.size() == 1) { + Arrays.sort(array); + return 1; + } + // 2) Recursive call sort() for each sliced array + for (Integer[] s: slices) { + count += sort(s); + } + // 3) Merge sliced arrays sequentially and verify elements are asc ordered. + List merged = new LinkedList<>(); + + Integer prev = null; + boolean sorted = true; + for (Integer[] slice: slices) { + + for (Integer el: slice) { + merged.add(el); + if (prev == null) { + prev = el; + continue; + } + if (el < prev) { + sorted = false; + } + } + } + // 4-1) if so, Assign the sorted array to the given array + // 4-2) otherwise, Re-sort the merged array and slice count is 1 + if (sorted) { + merged.toArray(array); + } else { + count = 1; + Arrays.sort(array); + } + // 5) Return the count of slices + return count; + } + + private List slice(Integer[] array) { + List slices = new ArrayList<>(); + + Integer prev = null; + List slice = new LinkedList<>(); + for (int i = 0; i < array.length; i++) { + if (prev == null) { + prev = array[i]; + slice.add(array[i]); + continue; + } + + if (array[i] < prev) { + slice.add(array[i]); + + Integer[] e = slice.toArray(new Integer[]{}); + slices.add(e); + prev = null; + slice = new LinkedList<>(); + } else { + prev = array[i]; + slice.add(array[i]); + if (i == array.length -1) { + slices.add(slice.toArray(new Integer[]{})); + } + } + } + return slices; + } +} diff --git a/src/test/java/com/company/problem/hard/SliceSortTest.java b/src/test/java/com/company/problem/hard/SliceSortTest.java new file mode 100644 index 0000000..d14511f --- /dev/null +++ b/src/test/java/com/company/problem/hard/SliceSortTest.java @@ -0,0 +1,46 @@ +package com.company.problem.hard; + +import org.junit.Test; +import org.junit.jupiter.api.Assertions; + +import static org.junit.jupiter.api.Assertions.*; + +public class SliceSortTest { + public SliceSort sliceSort = new SliceSort(); + + @Test + public void sample1() { + // Given + Integer[] given = {2, 4, 1, 6, 5, 9, 7}; + + // When + int slicedCount = sliceSort.sort(given); + + // Then + Assertions.assertEquals(3, slicedCount); + } + + @Test + public void sample2() { + // Given + Integer[] given = {4, 3, 2, 6, 1}; + + // When + int slicedCount = sliceSort.sort(given); + + // Then + Assertions.assertEquals(1, slicedCount); + } + + @Test + public void sample3() { + // Given + Integer[] given = {2, 1, 6, 4, 3, 7}; + + // When + int slicedCount = sliceSort.sort(given); + + // Then + Assertions.assertEquals(3, slicedCount); + } +}