I'm trying to solve this problem here. The question is all about finding the shortest sub array inside an array that contains all the element from 1 to K.
Input:
- The first line contains three space-separated integers N, K and Q. N is the length of actual Array, we need to find the shortest sub-array that contains all the element from 1 to K and Q is the number of queries.
- The second line contains N space-separated integers A1,A2,…,AN (the content for actual array).
There are two types of queries:
- Type 1 : 1 u v -> Update the value at position u to v.
- Type 2 : 2 -> Find the length of the shortest contiguous subarray which contain all the integers from 1 to K.
I wrote this code here, which I believe is efficient enough to be completed before desired time.
/* package codechef; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Codechef {
private static int findShortestContiguousSubArray(int[] array, int k) {
Map<Integer, Integer> mapElementAndCount = new HashMap<>();
for (int i = 1; i <= k; i++) {
mapElementAndCount.put(i, 1);
}
int count = k;
int cursor = 0;
int start = 0;
int minLength = Integer.MAX_VALUE;
while (cursor < array.length) {
if (mapElementAndCount.containsKey(array[cursor])) {
mapElementAndCount.put(array[cursor], mapElementAndCount.get(array[cursor]) - 1);
if(mapElementAndCount.get(array[cursor]) == 0) {
count--;
}
}
while (start < array.length && count == 0) {
if (minLength > cursor - start + 1) {
minLength = cursor - start + 1;
}
if(mapElementAndCount.keySet().contains(array[start])) {
mapElementAndCount.put(array[start], mapElementAndCount.get(array[start]) + 1);
if(mapElementAndCount.get(array[start]) == 1) {
count++;
}
}
start++;
}
cursor++;
}
return minLength == Integer.MAX_VALUE ? -1 : minLength;
}
public static void main (String[] args) throws java.lang.Exception {
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String firstLine = input.readLine();
String[] instructions = firstLine.trim().split(" ");
int n = Integer.parseInt(instructions[0]);
int k = Integer.parseInt(instructions[1]);
int q = Integer.parseInt(instructions[2]);
String[] stringArray = input.readLine().trim().split(" ");
int[] array = new int[stringArray.length];
for (int i = 0; i < n; i++) {
array[i] = Integer.parseInt(stringArray[i]);
}
while (q > 0) {
Integer.parseInt(instructions[0]);
String query = input.readLine();
instructions = query.trim().split(" ");
if (instructions.length == 1) {
System.out.println(findShortestContiguousSubArray(array, k));
} else if (instructions.length == 3) {
int targetIndex = Integer.parseInt(instructions[1]) - 1;
if (targetIndex >= array.length || targetIndex < 0) {
q--;
continue;
}
array[targetIndex] = Integer.parseInt(instructions[2]);
System.out.println();
}
q--;
}
}
}
Explanation:
I've created a map where I stored count 1 for each element in the range 1 to K (including K). After that I'm traversing the actual array and whenever I encounter an element which is there in the map, I reduce the value by 1 and reducing the count variable by 1 (I mean if the count of an element has become zero, I need to find K-1 rest elements in the range). And when the count variable becomes 0, which means I've found a sub array that contains all the element from 1 to K, then I compare it to the last encountered sub-array size (for the first time, I set it to Integer.MAX_VALUE) and I modify the size if I encounter small sub-array.
PROBLEM:
After submitting the code, it's showing time limit exceeded.
If this algorithm is fine, what is the problem in the code?
If this algorithm is not the best way to solve this problem, what else could be done (A brief demonstration of the algorithm would be sufficient)?
I'm asking question on this platform for the first time, so may be I'm not doing this in the best possible way. Please suggest the edit, I'll fix it.
Thank you in advance!
find()
algorithm is O(n²), and you're repeatedly doing that very same algorithm for every Type 2 query. There might be a betterfind()
algorithm, and there might be an incremental approach, taking into account that the Type 1 queries only change a single array element, thus allowing thefind()
to re-use some partial results from previous runs. \$\endgroup\$