For a given integer array of size n, find all possible sub arrays of size k which range from 1 to n.
Now find the common item which is also a minimum in all sub-arrays of size k, if no common item is found then use -1 and add that to the result list.
For example:
Input array : [4,3,3,4,2]
Result :
[-1,-1,3,3,2]
Explanation:
k = 1, [4],[3],[3],[4],[2], there is no common item so -1
k = 2, [4,3],[3,3],[3,4],[4,2], there is no common item so -1
k = 3, [4,3,3], [3,3,4], [3,4,2], common item is 3
k = 4, [4,3,3,4],[3,3,4,2], common items are 3 and 4, the minimum is 3
k = 5, [4,3,3,4,2], minimum common item is 2
This is my naive approach code along with comments:
public static List<Integer> solve(int[] ar) {
// Get all subarrays in a map, with key as sub-arrays size from 1 to n and value as the corresponding sub-arrays
Map<Integer, List<List<Integer>>> map = subArrays(ar);
int n = map.size();
List<Integer> result = new ArrayList<>();
for(int i=0; i<n; i++) {
List<List<Integer>> list = map.get(i+1);
// Get the common minimum item and store in result.
result.add(solve(list));
}
return result;
}
// Logic to check for a given subarray of size k, get the minimum common item
public static int solve(List<List<Integer>> list) {
int n = list.get(0).size();
int min = Integer.MAX_VALUE;
boolean found = false;
for (int i = 0; i < n; i++) {
int num = list.get(0).get(i);
boolean isCommon = true;
for(int j=1; j<list.size(); j++) {
List<Integer> arr = list.get(j);
if (!contains(arr, num)) {
isCommon = false;
break;
}
}
if (isCommon) {
min = Math.min(min, num);
found = true;
}
}
return found ? min : -1; // Return -1 if there is no common element.
}
// Logic to check if the number is present in given arr
public static boolean contains(List<Integer> arr, int num) {
for (int value : arr) {
if (value == num) {
return true;
}
}
return false;
}
// Logic to find all possible sub arrays of size 1 to n and stored in map
public static Map<Integer, List<List<Integer>>> subArrays(int[] arr) {
int n = arr.length;
Map<Integer, List<List<Integer>>> map = new HashMap<>();
for(int i=0; i<n; i++) {
map.put(i+1, new ArrayList<>());
}
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
int size = j - i+1;
List<Integer> e = new ArrayList<>();
for (int k = i; k <= j; k++) {
e.add(arr[k]);
}
map.get(size).add(e);
}
}
return map;
}
}
Here I am using a nested loop so time complexity is O(n^3), also using a map to store all possible sub-arrays that increase space complexity.
How to solve this in less time and less space.
Update:
I further tried to reduce time complexity using below code:
public static List<Integer> solve(int[] ar) {
int n = map.size();
List<Integer> result = new ArrayList<>();
for(int i=0; i<n; i++) {
result.add(minCommonElementInSubarrays(ar, i+1));
}
return result;
}
static void minCommonElementInSubarrays(int arr[], int K) {
int N = arr.length;
int c;
// If N is odd then update
// C as K >= (N + 1)/2
if ((N + 1) % 2 == 0)
{
c = (N + 1) / 2;
}
// If N is even then update
// C as K >= (N + 1)/2 + 1
else
{
c = (N + 1) / 2 + 1;
}
// If K < C, return "=1"
if (K < c)
{
return -1;
}
// Otherwise
else
{
// Initialize result variable
int ar = Integer.MAX_VALUE;
// Find minimum element
for(int i = N - K; i < K; i++)
{
ar = Math.min(arr[i], ar);
}
// return the minimum value
return ar;
}
}
But still this code runs in O(n^2) time complexity, I want to reduce it further.
solve(int[] ar)ismap? I read the problem statement to require common values; the improvement is about elements included in all sub-arrays of a specified size: try2, 1, 2, 1, 2. \$\endgroup\$