Working with a array that changes constantly - algorithm

Given an array , if 2 adjacent number are equal then they can merge and their value is increased by one. Find the smallest possible number of element left in the array after this process.
Ex: [1,1,1,2,1] ->[1,2,2,1]-> [1,3,1]. Thus the answer is 3.
I have tried using a linked list to store the array then iterate through the whole thing until no equal, adjacent number is detected but this seem very insufficent.
Any hint or suggestion is very appriciated. Thank you for your time

Here is a recursive solution, but I don't know if it is optimal:
Start with the smallest number in the array. In the example [1 1 1 2 1], it is 1. The reason is that you will not get new 1's after merging other elements. So they are easy to work with.
Obviously, if you have an even number of consecutive 1s, merging them all is never subobtimal. So, we need to decide what to do with an odd number of consecutive elements. One of them needs to be left out (not merged), and once we choose that one, remaining parts have both an even number of 1s.
The important observation here is that once you choose the element to be left out, the array to the left of it and the array to the right of it constitute two independent problems. Since there will be a single 1 in the middle, you can't merge any number at the right side with the left side. So, for every possible choice, you can recursively solve the problem for the right- and left-sub-arrays, and then find the minimum result.
Algorithm
To summarize the method, these are the steps to be followed:
If the length of array is 0, return 0.
Find the minimum element in the array. Call it x.
Go over the array one more time, create a new array where even number of consecutive x's are all merged.
If you saw an odd number of x's anywhere in the array, do this:
Let the index of first element be i. For each j = i, i+2, i+4, ... that belongs to the sequence of x's, solve the problem for sub-arrays [0 .. j-1] and [j+1 .. end]. Call their results n1 and n2.
Return the minimum n1 + n2 + 1 from these possible splits.
If you didn't see an odd number of x's, then there are no x's left in the array. Go back to step 1.
Note that you can substitute x's with x+1's in the 4th step, and choose the sub-problem indices accordingly, to possibly save some work in the recursive calls.
Code
Here is a c++ code that does this:
#include <iostream>
#include <limits>
#include <vector>
// the range is [start, end)
int
solve(std::vector<int>& array, int start, int end)
{
if (start >= end)
return 0;
int length = end - start;
// find the minimum element
int min = array[start];
for (int i = start; i < end; i++)
if (array[i] < min)
min = array[i];
std::vector<int> newArray;
newArray.reserve(length + 1);
int minCount = 0; // number of consecutive elements that are equal to min
int firstOddNumber =
-1; // index of an odd number of consecutive min's in the new array
int oddNumbers = 0; // number of min's starting at firstOddNumber
for (int i = start; i <= end; i++) {
// iterate one last time with i == end to run the checks again.
// hence the special case. we pop this element after the loop.
int elem = i < end ? array[i] : min + 1;
if (elem == min) {
minCount++;
} else if (minCount != 0) {
// even number of min's
if (minCount % 2 == 0) {
// merge them
for (int j = 0; j < minCount / 2; j++)
newArray.push_back(min + 1);
} else {
// do not merge them but save their index in the new array
firstOddNumber = newArray.size();
oddNumbers = minCount;
for (int j = 0; j < minCount; j++)
newArray.push_back(min);
// ^^^ this part could be modified as I wrote in the note in my
// answer
}
minCount = 0;
newArray.push_back(elem);
} else
newArray.push_back(elem);
}
// remove the min+1 element pushed when i == end
newArray.pop_back();
if (firstOddNumber == -1)
// no odd number of consecutive min's, repeat the procedure
return solve(newArray, 0, newArray.size());
else {
int minResult = newArray.size();
// solve two subproblems for each possible split
for (int i = firstOddNumber; i <= firstOddNumber + oddNumbers; i += 2) {
int result = 1 + solve(newArray, 0, i) +
solve(newArray, i + 1, newArray.size());
if (result < minResult)
minResult = result;
// ^^^ this part could be modified as I wrote in the note in my
// answer
}
return minResult;
}
}
void
test(std::vector<int> v, int expected)
{
int result = solve(v, 0, v.size());
std::cout << result << '\n';
if (result == expected)
std::cout << "CORRECT\n" << std::endl;
else
std::cout << "EXPECTED: " << expected << '\n' << std::endl;
}
int
main()
{
test({ 1, 1, 1, 2, 1 }, 3);
test({ 1, 1, 1, 1, 1 }, 2);
test({ 1, 1, 1, 1, 1, 1 }, 2);
test({ 1, 2, 1, 1, 1 }, 3);
test({ 1, 2, 1, 2, 1 }, 5);
}

I am assuming that the question requires reading the input from the end, instead of the start. Because if it required reading from the start then your second iteration must have been : [2, 1, 2, 1]
Assuming the question requires reading the input from the end, here's the solution:
Here's the algorithm:
Add all the elements to stack 1. Stack1: [1, 2, 1, 1, 1]; result:[] and top = 1;
Checking if 1 and 2 are equal, if not equal adding it to the result stack. result: [2, 1]
Checking if 1 and 1 are equal, if they are, incrementing the element and pushing the element to stack 1, and also adding all the result stack elements to stack1. Stack1: [1, 2, 2, 1], result: [].
Repeating the process until stack1 is empty.
class Solution {
public int mergeAdjacentSimilarElements(int[] arr) {
//stack 1
Stack stack = new Stack<>();
//stack 2
Stack result = new Stack<>();
//add all the elements to the stack, as stack follows LIFO, the last element would be at the top
for (int i = 0; i < arr.length; i++) {
stack.push(arr[i]);
}
while (!stack.isEmpty()) {
int top = !stack.isEmpty() ? stack.pop() : -1; // assign -1 in case stack is empty
int temp = !stack.isEmpty() ? stack.peek() : -1; // assign -1 in case stack is empty
//if top and temp are equal
if (top != -1 && temp != -1 && top == temp) {
stack.pop();
//increment the value of the top, and add it to stack
stack.push(++top);
//check if there are any elements in the result stack,
// as they have to be added to stack1, as stack1 is modified.
if (!result.isEmpty()) {
stack.push(result.pop());
}
} else {
//else simply add the element to the stack.
result.push(top);
}
}
//for testing
result.stream().forEach(System.out::println);
return result.size();
}
}

Related

How to maintain a min sliding window for an unsorted array? [duplicate]

Given an array of size n and k, how do you find the maximum for every contiguous subarray of size k?
For example
arr = 1 5 2 6 3 1 24 7
k = 3
ans = 5 6 6 6 24 24
I was thinking of having an array of size k and each step evict the last element out and add the new element and find maximum among that. It leads to a running time of O(nk). Is there a better way to do this?
You have heard about doing it in O(n) using dequeue.
Well that is a well known algorithm for this question to do in O(n).
The method i am telling is quite simple and has time complexity O(n).
Your Sample Input:
n=10 , W = 3
10 3
1 -2 5 6 0 9 8 -1 2 0
Answer = 5 6 6 9 9 9 8 2
Concept: Dynamic Programming
Algorithm:
N is number of elements in an array and W is window size. So, Window number = N-W+1
Now divide array into blocks of W starting from index 1.
Here divide into blocks of size 'W'=3.
For your sample input:
We have divided into blocks because we will calculate maximum in 2 ways A.) by traversing from left to right B.) by traversing from right to left.
but how ??
Firstly, Traversing from Left to Right. For each element ai in block we will find maximum till that element ai starting from START of Block to END of that block.
So here,
Secondly, Traversing from Right to Left. For each element 'ai' in block we will find maximum till that element 'ai' starting from END of Block to START of that block.
So Here,
Now we have to find maximum for each subarray or window of size 'W'.
So, starting from index = 1 to index = N-W+1 .
max_val[index] = max(RL[index], LR[index+w-1]);
for index=1: max_val[1] = max(RL[1],LR[3]) = max(5,5)= 5
Simliarly, for all index i, (i<=(n-k+1)), value at RL[i] and LR[i+w-1]
are compared and maximum among those two is answer for that subarray.
So Final Answer : 5 6 6 9 9 9 8 2
Time Complexity: O(n)
Implementation code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LIM 100001
using namespace std;
int arr[LIM]; // Input Array
int LR[LIM]; // maximum from Left to Right
int RL[LIM]; // maximum from Right to left
int max_val[LIM]; // number of subarrays(windows) will be n-k+1
int main(){
int n, w, i, k; // 'n' is number of elements in array
// 'w' is Window's Size
cin >> n >> w;
k = n - w + 1; // 'K' is number of Windows
for(i = 1; i <= n; i++)
cin >> arr[i];
for(i = 1; i <= n; i++){ // for maximum Left to Right
if(i % w == 1) // that means START of a block
LR[i] = arr[i];
else
LR[i] = max(LR[i - 1], arr[i]);
}
for(i = n; i >= 1; i--){ // for maximum Right to Left
if(i == n) // Maybe the last block is not of size 'W'.
RL[i] = arr[i];
else if(i % w == 0) // that means END of a block
RL[i] = arr[i];
else
RL[i] = max(RL[i+1], arr[i]);
}
for(i = 1; i <= k; i++) // maximum
max_val[i] = max(RL[i], LR[i + w - 1]);
for(i = 1; i <= k ; i++)
cout << max_val[i] << " ";
cout << endl;
return 0;
}
Running Code Link
I'll try to proof: (by #johnchen902)
If k % w != 1 (k is not the begin of a block)
Let k* = The begin of block containing k
ans[k] = max( arr[k], arr[k + 1], arr[k + 2], ..., arr[k + w - 1])
= max( max( arr[k], arr[k + 1], arr[k + 2], ..., arr[k*]),
max( arr[k*], arr[k* + 1], arr[k* + 2], ..., arr[k + w - 1]) )
= max( RL[k], LR[k+w-1] )
Otherwise (k is the begin of a block)
ans[k] = max( arr[k], arr[k + 1], arr[k + 2], ..., arr[k + w - 1])
= RL[k] = LR[k+w-1]
= max( RL[k], LR[k+w-1] )
Dynamic programming approach is very neatly explained by Shashank Jain. I would like to explain how to do the same using dequeue.
The key is to maintain the max element at the top of the queue(for a window ) and discarding the useless elements and we also need to discard the elements that are out of index of current window.
useless elements = If Current element is greater than the last element of queue than the last element of queue is useless .
Note : We are storing the index in queue not the element itself. It will be more clear from the code itself.
1. If Current element is greater than the last element of queue than the last element of queue is useless . We need to delete that last element.
(and keep deleting until the last element of queue is smaller than current element).
2. If if current_index - k >= q.front() that means we are going out of window so we need to delete the element from front of queue.
vector<int> max_sub_deque(vector<int> &A,int k)
{
deque<int> q;
for(int i=0;i<k;i++)
{
while(!q.empty() && A[i] >= A[q.back()])
q.pop_back();
q.push_back(i);
}
vector<int> res;
for(int i=k;i<A.size();i++)
{
res.push_back(A[q.front()]);
while(!q.empty() && A[i] >= A[q.back()] )
q.pop_back();
while(!q.empty() && q.front() <= i-k)
q.pop_front();
q.push_back(i);
}
res.push_back(A[q.front()]);
return res;
}
Since each element is enqueued and dequeued atmost 1 time to time complexity is O(n+n) = O(2n) = O(n).
And the size of queue can not exceed the limit k . so space complexity = O(k).
An O(n) time solution is possible by combining the two classic interview questions:
Make a stack data-structure (called MaxStack) which supports push, pop and max in O(1) time.
This can be done using two stacks, the second one contains the minimum seen so far.
Model a queue with a stack.
This can done using two stacks. Enqueues go into one stack, and dequeues come from the other.
For this problem, we basically need a queue, which supports enqueue, dequeue and max in O(1) (amortized) time.
We combine the above two, by modelling a queue with two MaxStacks.
To solve the question, we queue k elements, query the max, dequeue, enqueue k+1 th element, query the max etc. This will give you the max for every k sized sub-array.
I believe there are other solutions too.
1)
I believe the queue idea can be simplified. We maintain a queue and a max for every k. We enqueue a new element, and dequeu all elements which are not greater than the new element.
2) Maintain two new arrays which maintain the running max for each block of k, one array for one direction (left to right/right to left).
3) Use a hammer: Preprocess in O(n) time for range maximum queries.
The 1) solution above might be the most optimal.
You need a fast data structure that can add, remove and query for the max element in less than O(n) time (you can just use an array if O(n) or O(nlogn) is acceptable). You can use a heap, a balanced binary search tree, a skip list, or any other sorted data structure that performs these operations in O(log(n)).
The good news is that most popular languages have a sorted data structure implemented that supports these operations for you. C++ has std::set and std::multiset (you probably need the latter) and Java has PriorityQueue and TreeSet.
Here is the java implementation
public static Integer[] maxsInEveryWindows(int[] arr, int k) {
Deque<Integer> deque = new ArrayDeque<Integer>();
/* Process first k (or first window) elements of array */
for (int i = 0; i < k; i++) {
// For very element, the previous smaller elements are useless so
// remove them from deque
while (!deque.isEmpty() && arr[i] >= arr[deque.peekLast()]) {
deque.removeLast(); // Remove from rear
}
// Add new element at rear of queue
deque.addLast(i);
}
List<Integer> result = new ArrayList<Integer>();
// Process rest of the elements, i.e., from arr[k] to arr[n-1]
for (int i = k; i < arr.length; i++) {
// The element at the front of the queue is the largest element of
// previous window, so add to result.
result.add(arr[deque.getFirst()]);
// Remove all elements smaller than the currently
// being added element (remove useless elements)
while (!deque.isEmpty() && arr[i] >= arr[deque.peekLast()]) {
deque.removeLast();
}
// Remove the elements which are out of this window
while (!deque.isEmpty() && deque.getFirst() <= i - k) {
deque.removeFirst();
}
// Add current element at the rear of deque
deque.addLast(i);
}
// Print the maximum element of last window
result.add(arr[deque.getFirst()]);
return result.toArray(new Integer[0]);
}
Here is the corresponding test case
#Test
public void maxsInWindowsOfSizeKTest() {
Integer[] result = ArrayUtils.maxsInEveryWindows(new int[]{1, 2, 3, 1, 4, 5, 2, 3, 6}, 3);
assertThat(result, equalTo(new Integer[]{3, 3, 4, 5, 5, 5, 6}));
result = ArrayUtils.maxsInEveryWindows(new int[]{8, 5, 10, 7, 9, 4, 15, 12, 90, 13}, 4);
assertThat(result, equalTo(new Integer[]{10, 10, 10, 15, 15, 90, 90}));
}
Using a heap (or tree), you should be able to do it in O(n * log(k)). I'm not sure if this would be indeed better.
here is the Python implementation in O(1)...Thanks to #Shahshank Jain in advance..
from sys import stdin,stdout
from operator import *
n,w=map(int , stdin.readline().strip().split())
Arr=list(map(int , stdin.readline().strip().split()))
k=n-w+1 # window size = k
leftA=[0]*n
rightA=[0]*n
result=[0]*k
for i in range(n):
if i%w==0:
leftA[i]=Arr[i]
else:
leftA[i]=max(Arr[i],leftA[i-1])
for i in range(n-1,-1,-1):
if i%w==(w-1) or i==n-1:
rightA[i]=Arr[i]
else:
rightA[i]=max(Arr[i],rightA[i+1])
for i in range(k):
result[i]=max(rightA[i],leftA[i+w-1])
print(*result,sep=' ')
Method 1: O(n) time, O(k) space
We use a deque (it is like a list but with constant-time insertion and deletion from both ends) to store the index of useful elements.
The index of the current max is kept at the leftmost element of deque. The rightmost element of deque is the smallest.
In the following, for easier explanation we say an element from the array is in the deque, while in fact the index of that element is in the deque.
Let's say {5, 3, 2} are already in the deque (again, if fact their indexes are).
If the next element we read from the array is bigger than 5 (remember, the leftmost element of deque holds the max), say 7: We delete the deque and create a new one with only 7 in it (we do this because the current elements are useless, we have found a new max).
If the next element is less than 2 (which is the smallest element of deque), say 1: We add it to the right ({5, 3, 2, 1})
If the next element is bigger than 2 but less than 5, say 4: We remove elements from right that are smaller than the element and then add the element from right ({5, 4}).
Also we keep elements of the current window only (we can do this in constant time because we are storing the indexes instead of elements).
from collections import deque
def max_subarray(array, k):
deq = deque()
for index, item in enumerate(array):
if len(deq) == 0:
deq.append(index)
elif index - deq[0] >= k: # the max element is out of the window
deq.popleft()
elif item > array[deq[0]]: # found a new max
deq = deque()
deq.append(index)
elif item < array[deq[-1]]: # the array item is smaller than all the deque elements
deq.append(index)
elif item > array[deq[-1]] and item < array[deq[0]]:
while item > array[deq[-1]]:
deq.pop()
deq.append(index)
if index >= k - 1: # start printing when the first window is filled
print(array[deq[0]])
Proof of O(n) time: The only part we need to check is the while loop. In the whole runtime of the code, the while loop can perform at most O(n) operations in total. The reason is that the while loop pops elements from the deque, and since in other parts of the code, we do at most O(n) insertions into the deque, the while loop cannot exceed O(n) operations in total. So the total runtime is O(n) + O(n) = O(n)
Method 2: O(n) time, O(n) space
This is the explanation of the method suggested by S Jain (as mentioned in the comments of his post, this method doesn't work with data streams, which most sliding window questions are designed for).
The reason that method works is explained using the following example:
array = [5, 6, 2, 3, 1, 4, 2, 3]
k = 4
[5, 6, 2, 3 1, 4, 2, 3 ]
LR: 5 6 6 6 1 4 4 4
RL: 6 6 3 3 4 4 3 3
6 6 4 4 4
To get the max for the window [2, 3, 1, 4],
we can get the max of [2, 3] and max of [1, 4], and return the bigger of the two.
Max of [2, 3] is calculated in the RL pass and max of [1, 4] is calculated in LR pass.
Using Fibonacci heap, you can do it in O(n + (n-k) log k), which is equal to O(n log k) for small k, for k close to n this becomes O(n).
The algorithm: in fact, you need:
n inserts to the heap
n-k deletions
n-k findmax's
How much these operations cost in Fibonacci heaps? Insert and findmax is O(1) amortized, deletion is O(log n) amortized. So, we have
O(n + (n-k) log k + (n-k)) = O(n + (n-k) log k)
Sorry, this should have been a comment but I am not allowed to comment for now.
#leo and #Clay Goddard
You can save yourselves from re-computing the maximum by storing both maximum and 2nd maximum of the window in the beginning
(2nd maximum will be the maximum only if there are two maximums in the initial window). If the maximum slides out of the window you still have the next best candidate to compare with the new entry. So you get O(n) , otherwise if you allowed the whole re-computation again the worst case order would be O(nk), k is the window size.
class MaxFinder
{
// finds the max and its index
static int[] findMaxByIteration(int arr[], int start, int end)
{
int max, max_ndx;
max = arr[start];
max_ndx = start;
for (int i=start; i<end; i++)
{
if (arr[i] > max)
{
max = arr[i];
max_ndx = i;
}
}
int result[] = {max, max_ndx};
return result;
}
// optimized to skip iteration, when previous windows max element
// is present in current window
static void optimizedPrintKMax(int arr[], int n, int k)
{
int i, j, max, max_ndx;
// for first window - find by iteration.
int result[] = findMaxByIteration(arr, 0, k);
System.out.printf("%d ", result[0]);
max = result[0];
max_ndx = result[1];
for (j=1; j <= (n-k); j++)
{
// if previous max has fallen out of current window, iterate and find
if (max_ndx < j)
{
result = findMaxByIteration(arr, j, j+k);
max = result[0];
max_ndx = result[1];
}
// optimized path, just compare max with new_elem that has come into the window
else
{
int new_elem_ndx = j + (k-1);
if (arr[new_elem_ndx] > max)
{
max = arr[new_elem_ndx];
max_ndx = new_elem_ndx;
}
}
System.out.printf("%d ", max);
}
}
public static void main(String[] args)
{
int arr[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
//int arr[] = {1,5,2,6,3,1,24,7};
int n = arr.length;
int k = 3;
optimizedPrintKMax(arr, n, k);
}
}
package com;
public class SlidingWindow {
public static void main(String[] args) {
int[] array = { 1, 5, 2, 6, 3, 1, 24, 7 };
int slide = 3;//say
List<Integer> result = new ArrayList<Integer>();
for (int i = 0; i < array.length - (slide-1); i++) {
result.add(getMax(array, i, slide));
}
System.out.println("MaxList->>>>" + result.toString());
}
private static Integer getMax(int[] array, int i, int slide) {
List<Integer> intermediate = new ArrayList<Integer>();
System.out.println("Initial::" + intermediate.size());
while (intermediate.size() < slide) {
intermediate.add(array[i]);
i++;
}
Collections.sort(intermediate);
return intermediate.get(slide - 1);
}
}
Here is the solution in O(n) time complexity with auxiliary deque
public class TestSlidingWindow {
public static void main(String[] args) {
int[] arr = { 1, 5, 7, 2, 1, 3, 4 };
int k = 3;
printMaxInSlidingWindow(arr, k);
}
public static void printMaxInSlidingWindow(int[] arr, int k) {
Deque<Integer> queue = new ArrayDeque<Integer>();
Deque<Integer> auxQueue = new ArrayDeque<Integer>();
int[] resultArr = new int[(arr.length - k) + 1];
int maxElement = 0;
int j = 0;
for (int i = 0; i < arr.length; i++) {
queue.add(arr[i]);
if (arr[i] > maxElement) {
maxElement = arr[i];
}
/** we need to maintain the auxiliary deque to maintain max element in case max element is removed.
We add the element to deque straight away if subsequent element is less than the last element
(as there is a probability if last element is removed this element can be max element) otherwise
remove all lesser element then insert current element **/
if (auxQueue.size() > 0) {
if (arr[i] < auxQueue.peek()) {
auxQueue.push(arr[i]);
} else {
while (auxQueue.size() > 0 && (arr[i] > auxQueue.peek())) {
auxQueue.pollLast();
}
auxQueue.push(arr[i]);
}
}else {
auxQueue.push(arr[i]);
}
if (queue.size() > 3) {
int removedEl = queue.removeFirst();
if (maxElement == removedEl) {
maxElement = auxQueue.pollFirst();
}
}
if (queue.size() == 3) {
resultArr[j++] = maxElement;
}
}
for (int i = 0; i < resultArr.length; i++) {
System.out.println(resultArr[i]);
}
}
}
static void countDistinct(int arr[], int n, int k)
{
System.out.print("\nMaximum integer in the window : ");
// Traverse through every window
for (int i = 0; i <= n - k; i++) {
System.out.print(findMaximuminAllWindow(Arrays.copyOfRange(arr, i, arr.length), k)+ " ");
}
}
private static int findMaximuminAllWindow(int[] win, int k) {
// TODO Auto-generated method stub
int max= Integer.MIN_VALUE;
for(int i=0; i<k;i++) {
if(win[i]>max)
max=win[i];
}
return max;
}
arr = 1 5 2 6 3 1 24 7
We have to find the maximum of subarray, Right?
So, What is meant by subarray?
SubArray = Partial set and it should be in order and contiguous.
From the above array
{1,5,2} {6,3,1} {1,24,7} all are the subarray examples
n = 8 // Array length
k = 3 // window size
For finding the maximum, we have to iterate through the array, and find the maximum.
From the window size k,
{1,5,2} = 5 is the maximum
{5,2,6} = 6 is the maximum
{2,6,3} = 6 is the maximum
and so on..
ans = 5 6 6 6 24 24
It can be evaluated as the n-k+1
Hence, 8-3+1 = 6
And the length of an answer is 6 as we seen.
How can we solve this now?
When the data is moving from the pipe, the first thought for the data structure came in mind is the Queue
But, rather we are not discussing much here, we directly jump on the deque
Thinking Would be:
Window is fixed and data is in and out
Data is fixed and window is sliding
EX: Time series database
While (Queue is not empty and arr[Queue.back() < arr[i]] {
Queue.pop_back();
Queue.push_back();
For the rest:
Print the front of queue
// purged expired element
While (queue not empty and queue.front() <= I-k) {
Queue.pop_front();
While (Queue is not empty and arr[Queue.back() < arr[i]] {
Queue.pop_back();
Queue.push_back();
}
}
arr = [1, 2, 3, 1, 4, 5, 2, 3, 6]
k = 3
for i in range(len(arr)-k):
k=k+1
print (max(arr[i:k]),end=' ') #3 3 4 5 5 5 6
Two approaches.
Segment Tree O(nlog(n-k))
Build a maximum segment-tree.
Query between [i, i+k)
Something like..
public static void printMaximums(int[] a, int k) {
int n = a.length;
SegmentTree tree = new SegmentTree(a);
for (int i=0; i<=n-k; i++) System.out.print(tree.query(i, i+k));
}
Deque O(n)
If the next element is greater than the rear element, remove the rear element.
If the element in the front of the deque is out of the window, remove the front element.
public static void printMaximums(int[] a, int k) {
int n = a.length;
Deque<int[]> deck = new ArrayDeque<>();
List<Integer> result = new ArrayList<>();
for (int i=0; i<n; i++) {
while (!deck.isEmpty() && a[i] >= deck.peekLast()[0]) deck.pollLast();
deck.offer(new int[] {a[i], i});
while (!deck.isEmpty() && deck.peekFirst()[1] <= i - k) deck.pollFirst();
if (i >= k - 1) result.add(deck.peekFirst()[0]);
}
System.out.println(result);
}
Here is an optimized version of the naive (conditional) nested loop approach I came up with which is much faster and doesn't require any auxiliary storage or data structure.
As the program moves from window to window, the start index and end index moves forward by 1. In other words, two consecutive windows have adjacent start and end indices.
For the first window of size W , the inner loop finds the maximum of elements with index (0 to W-1). (Hence i == 0 in the if in 4th line of the code).
Now instead of computing for the second window which only has one new element, since we have already computed the maximum for elements of indices 0 to W-1, we only need to compare this maximum to the only new element in the new window with the index W.
But if the element at 0 was the maximum which is the only element not part of the new window, we need to compute the maximum using the inner loop from 1 to W again using the inner loop (hence the second condition maxm == arr[i-1] in the if in line 4), otherwise just compare the maximum of the previous window and the only new element in the new window.
void print_max_for_each_subarray(int arr[], int n, int k)
{
int maxm;
for(int i = 0; i < n - k + 1 ; i++)
{
if(i == 0 || maxm == arr[i-1]) {
maxm = arr[i];
for(int j = i+1; j < i+k; j++)
if(maxm < arr[j]) maxm = arr[j];
}
else {
maxm = maxm < arr[i+k-1] ? arr[i+k-1] : maxm;
}
cout << maxm << ' ';
}
cout << '\n';
}
You can use Deque data structure to implement this. Deque has an unique facility that you can insert and remove elements from both the ends of the queue unlike the traditional queue where you can only insert from one end and remove from other.
Following is the code for the above problem.
public int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length;
int[] maxInWindow = new int[n - k + 1];
Deque<Integer> dq = new LinkedList<Integer>();
int i = 0;
for(; i<k; i++){
while(!dq.isEmpty() && nums[dq.peekLast()] <= nums[i]){
dq.removeLast();
}
dq.addLast(i);
}
for(; i <n; i++){
maxInWindow[i - k] = nums[dq.peekFirst()];
while(!dq.isEmpty() && dq.peekFirst() <= i - k){
dq.removeFirst();
}
while(!dq.isEmpty() && nums[dq.peekLast()] <= nums[i]){
dq.removeLast();
}
dq.addLast(i);
}
maxInWindow[i - k] = nums[dq.peekFirst()];
return maxInWindow;
}
the resultant array will have n - k + 1 elements where n is length of the given array, k is the given window size.
We can solve it using the Python , applying the slicing.
def sliding_window(a,k,n):
max_val =[]
val =[]
val1=[]
for i in range(n-k-1):
if i==0:
val = a[0:k+1]
print("The value in val variable",val)
val1 = max(val)
max_val.append(val1)
else:
val = a[i:i*k+1]
val1 =max(val)
max_val.append(val1)
return max_val
Driver Code
a = [15,2,3,4,5,6,2,4,9,1,5]
n = len(a)
k = 3
sl=s liding_window(a,k,n)
print(sl)
Create a TreeMap of size k. Put first k elements as keys in it and assign any value like 1(doesn't matter). TreeMap has the property to sort the elements based on key so now, first element in map will be min and last element will be max element. Then remove 1 element from the map whose index in the arr is i-k. Here, I have considered that Input elements are taken in array arr and from that array we are filling the map of size k. Since, we can't do anything with sorting happening inside TreeMap, therefore this approach will also take O(n) time.
100% working Tested (Swift)
func maxOfSubArray(arr:[Int],n:Int,k:Int)->[Int]{
var lenght = arr.count
var resultArray = [Int]()
for i in 0..<arr.count{
if lenght+1 > k{
let tempArray = Array(arr[i..<k+i])
resultArray.append(tempArray.max()!)
}
lenght = lenght - 1
}
print(resultArray)
return resultArray
}
This way we can use:
maxOfSubArray(arr: [1,2,3,1,4,5,2,3,6], n: 9, k: 3)
Result:
[3, 3, 4, 5, 5, 5, 6]
Just notice that you only have to find in the new window if:
* The new element in the window is smaller than the previous one (if it's bigger, it's for sure this one).
OR
* The element that just popped out of the window was the current bigger.
In this case, re-scan the window.
for how big k? for reasonable-sized k. you can create k k-sized buffers and just iterate over the array keeping track of max element pointers in the buffers - needs no data structures and is O(n) k^2 pre-allocation.
A complete working solution in Amortised Constant O(1) Complexity.
https://github.com/varoonverma/code-challenge.git
Compare the first k elements and find the max, this is your first number
then compare the next element to the previous max. If the next element is bigger, that is your max of the next subarray, if its equal or smaller, the max for that sub array is the same
then move on to the next number
max(1 5 2) = 5
max(5 6) = 6
max(6 6) = 6
... and so on
max(3 24) = 24
max(24 7) = 24
It's only slightly better than your answer

How to perform K-swap operations on an N-digit integer to get maximum possible number

I recently went through an interview and was asked this question. Let me explain the question properly:
Given a number M (N-digit integer) and K number of swap operations(a swap
operation can swap 2 digits), devise an algorithm to get the maximum
possible integer?
Examples:
M = 132 K = 1 output = 312
M = 132 K = 2 output = 321
M = 7899 k = 2 output = 9987
My solution ( algorithm in pseudo-code). I used a max-heap to get the maximum digit out of N-digits in each of the K-operations and then suitably swapping it.
for(int i = 0; i<K; i++)
{
int max_digit_currently = GetMaxFromHeap();
// The above function GetMaxFromHeap() pops out the maximum currently and deletes it from heap
int index_to_swap_with = GetRightMostOccurenceOfTheDigitObtainedAbove();
// This returns me the index of the digit obtained in the previous function
// .e.g If I have 436659 and K=2 given,
// then after K=1 I'll have 936654 and after K=2, I should have 966354 and not 963654.
// Now, the swap part comes. Here the gotcha is, say with the same above example, I have K=3.
// If I do GetMaxFromHeap() I'll get 6 when K=3, but I should not swap it,
// rather I should continue for next iteration and
// get GetMaxFromHeap() to give me 5 and then get 966534 from 966354.
if (Value_at_index_to_swap == max_digit_currently)
continue;
else
DoSwap();
}
Time complexity: O(K*( N + log_2(N) ))
// K-times [log_2(N) for popping out number from heap & N to get the rightmost index to swap with]
The above strategy fails in this example:
M = 8799 and K = 2
Following my strategy, I'll get M = 9798 after K=1 and M = 9978 after K=2. However, the maximum I can get is M = 9987 after K=2.
What did I miss?
Also suggest other ways to solve the problem & ways to optimize my solution.
I think the missing part is that, after you've performed the K swaps as in the algorithm described by the OP, you're left with some numbers that you can swap between themselves. For example, for the number 87949, after the initial algorithm we would get 99748. However, after that we can swap 7 and 8 "for free", i.e. not consuming any of the K swaps. This would mean "I'd rather not swap the 7 with the second 9 but with the first".
So, to get the max number, one would perform the algorithm described by the OP and remember the numbers which were moved to the right, and the positions to which they were moved. Then, sort these numbers in decreasing order and put them in the positions from left to right.
This is something like a separation of the algorithm in two phases - in the first one, you choose which numbers should go in the front to maximize the first K positions. Then you determine the order in which you would have swapped them with the numbers whose positions they took, so that the rest of the number is maximized as well.
Not all the details are clear, and I'm not 100% sure it handles all cases correctly, so if anyone can break it - go ahead.
This is a recursive function, which sorts the possible swap values for each (current-max) digit:
function swap2max(string, K) {
// the recursion end:
if (string.length==0 || K==0)
return string
m = getMaxDigit(string)
// an array of indices of the maxdigits to swap in the string
indices = []
// a counter for the length of that array, to determine how many chars
// from the front will be swapped
len = 0
// an array of digits to be swapped
front = []
// and the index of the last of those:
right = 0
// get those indices, in a loop with 2 conditions:
// * just run backwards through the string, until we meet the swapped range
// * no more swaps than left (K)
for (i=string.length; i-->right && len<K;)
if (m == string[i])
// omit digits that are already in the right place
while (right<=i && string[right] == m)
right++
// and when they need to be swapped
if (i>=right)
front.push(string[right++])
indices.push(i)
len++
// sort the digits to swap with
front.sort()
// and swap them
for (i=0; i<len; i++)
string.setCharAt(indices[i], front[i])
// the first len digits are the max ones
// the rest the result of calling the function on the rest of the string
return m.repeat(right) + swap2max(string.substr(right), K-len)
}
This is all pseudocode, but converts fairly easy to other languages. This solution is nonrecursive and operates in linear worst case and average case time.
You are provided with the following functions:
function k_swap(n, k1, k2):
temp = n[k1]
n[k1] = n[k2]
n[k2] = temp
int : operator[k]
// gets or sets the kth digit of an integer
property int : magnitude
// the number of digits in an integer
You could do something like the following:
int input = [some integer] // input value
int digitcounts[10] = {0, ...} // all zeroes
int digitpositions[10] = {0, ...) // all zeroes
bool filled[input.magnitude] = {false, ...) // all falses
for d = input[i = 0 => input.magnitude]:
digitcounts[d]++ // count number of occurrences of each digit
digitpositions[0] = 0;
for i = 1 => input.magnitude:
digitpositions[i] = digitpositions[i - 1] + digitcounts[i - 1] // output positions
for i = 0 => input.magnitude:
digit = input[i]
if filled[i] == true:
continue
k_swap(input, i, digitpositions[digit])
filled[digitpositions[digit]] = true
digitpositions[digit]++
I'll walk through it with the number input = 724886771
computed digitcounts:
{0, 1, 1, 0, 1, 0, 1, 3, 2, 0}
computed digitpositions:
{0, 0, 1, 2, 2, 3, 3, 4, 7, 9}
swap steps:
swap 0 with 0: 724886771, mark 0 visited
swap 1 with 4: 724876781, mark 4 visited
swap 2 with 5: 724778881, mark 5 visited
swap 3 with 3: 724778881, mark 3 visited
skip 4 (already visited)
skip 5 (already visited)
swap 6 with 2: 728776481, mark 2 visited
swap 7 with 1: 788776421, mark 1 visited
swap 8 with 6: 887776421, mark 6 visited
output number: 887776421
Edit:
This doesn't address the question correctly. If I have time later, I'll fix it but I don't right now.
How I would do it (in pseudo-c -- nothing fancy), assuming a fantasy integer array is passed where each element represents one decimal digit:
int[] sortToMaxInt(int[] M, int K) {
for (int i = 0; K > 0 && i < M.size() - 1; i++) {
if (swapDec(M, i)) K--;
}
return M;
}
bool swapDec(int[]& M, int i) {
/* no need to try and swap the value 9 as it is the
* highest possible value anyway. */
if (M[i] == 9) return false;
int max_dec = 0;
int max_idx = 0;
for (int j = i+1; j < M.size(); j++) {
if (M[j] >= max_dec) {
max_idx = j;
max_dec = M[j];
}
}
if (max_dec > M[i]) {
M.swapElements(i, max_idx);
return true;
}
return false;
}
From the top of my head so if anyone spots some fatal flaw please let me know.
Edit: based on the other answers posted here, I probably grossly misunderstood the problem. Anyone care to elaborate?
You start with max-number(M, N, 1, K).
max-number(M, N, pos, k)
{
if k == 0
return M
max-digit = 0
for i = pos to N
if M[i] > max-digit
max-digit = M[i]
if M[pos] == max-digit
return max-number(M, N, pos + 1, k)
for i = (pos + 1) to N
maxs.add(M)
if M[i] == max-digit
M2 = new M
swap(M2, i, pos)
maxs.add(max-number(M2, N, pos + 1, k - 1))
return maxs.max()
}
Here's my approach (It's not fool-proof, but covers the basic cases). First we'll need a function that extracts each DIGIT of an INT into a container:
std::shared_ptr<std::deque<int>> getDigitsOfInt(const int N)
{
int number(N);
std::shared_ptr<std::deque<int>> digitsQueue(new std::deque<int>());
while (number != 0)
{
digitsQueue->push_front(number % 10);
number /= 10;
}
return digitsQueue;
}
You obviously want to create the inverse of this, so convert such a container back to an INT:
const int getIntOfDigits(const std::shared_ptr<std::deque<int>>& digitsQueue)
{
int number(0);
for (std::deque<int>::size_type i = 0, iMAX = digitsQueue->size(); i < iMAX; ++i)
{
number = number * 10 + digitsQueue->at(i);
}
return number;
}
You also will need to find the MAX_DIGIT. It would be great to use std::max_element as it returns an iterator to the maximum element of a container, but if there are more you want the last of them. So let's implement our own max algorithm:
int getLastMaxDigitOfN(const std::shared_ptr<std::deque<int>>& digitsQueue, int startPosition)
{
assert(!digitsQueue->empty() && digitsQueue->size() > startPosition);
int maxDigitPosition(0);
int maxDigit(digitsQueue->at(startPosition));
for (std::deque<int>::size_type i = startPosition, iMAX = digitsQueue->size(); i < iMAX; ++i)
{
const int currentDigit(digitsQueue->at(i));
if (maxDigit <= currentDigit)
{
maxDigit = currentDigit;
maxDigitPosition = i;
}
}
return maxDigitPosition;
}
From here on its pretty straight what you have to do, put the right-most (last) MAX DIGITS to their places until you can swap:
const int solution(const int N, const int K)
{
std::shared_ptr<std::deque<int>> digitsOfN = getDigitsOfInt(N);
int pos(0);
int RemainingSwaps(K);
while (RemainingSwaps)
{
int lastHDPosition = getLastMaxDigitOfN(digitsOfN, pos);
if (lastHDPosition != pos)
{
std::swap<int>(digitsOfN->at(lastHDPosition), digitsOfN->at(pos));
++pos;
--RemainingSwaps;
}
}
return getIntOfDigits(digitsOfN);
}
There are unhandled corner-cases but I'll leave that up to you.
I assumed K = 2, but you can change the value!
Java code
public class Solution {
public static void main (String args[]) {
Solution d = new Solution();
System.out.println(d.solve(1234));
System.out.println(d.solve(9812));
System.out.println(d.solve(9876));
}
public int solve(int number) {
int[] array = intToArray(number);
int[] result = solve(array, array.length-1, 2);
return arrayToInt(result);
}
private int arrayToInt(int[] array) {
String s = "";
for (int i = array.length-1 ;i >= 0; i--) {
s = s + array[i]+"";
}
return Integer.parseInt(s);
}
private int[] intToArray(int number){
String s = number+"";
int[] result = new int[s.length()];
for(int i = 0 ;i < s.length() ;i++) {
result[s.length()-1-i] = Integer.parseInt(s.charAt(i)+"");
}
return result;
}
private int[] solve(int[] array, int endIndex, int num) {
if (endIndex == 0)
return array;
int size = num ;
int firstIndex = endIndex - size;
if (firstIndex < 0)
firstIndex = 0;
int biggest = findBiggestIndex(array, endIndex, firstIndex);
if (biggest!= endIndex) {
if (endIndex-biggest==num) {
while(num!=0) {
int temp = array[biggest];
array[biggest] = array[biggest+1];
array[biggest+1] = temp;
biggest++;
num--;
}
return array;
}else{
int n = endIndex-biggest;
for (int i = 0 ;i < n;i++) {
int temp = array[biggest];
array[biggest] = array[biggest+1];
array[biggest+1] = temp;
biggest++;
}
return solve(array, --biggest, firstIndex);
}
}else{
return solve(array, --endIndex, num);
}
}
private int findBiggestIndex(int[] array, int endIndex, int firstIndex) {
int result = firstIndex;
int max = array[firstIndex];
for (int i = firstIndex; i <= endIndex; i++){
if (array[i] > max){
max = array[i];
result = i;
}
}
return result;
}
}

Find the first "missing" number in a sorted list

Let's say I have the continuous range of integers [0, 1, 2, 4, 6], in which the 3 is the first "missing" number. I need an algorithm to find this first "hole". Since the range is very large (containing perhaps 2^32 entries), efficiency is important. The range of numbers is stored on disk; space efficiency is also a main concern.
What's the best time and space efficient algorithm?
Use binary search. If a range of numbers has no hole, then the difference between the end and start of the range will also be the number of entries in the range.
You can therefore begin with the entire list of numbers, and chop off either the first or second half based on whether the first half has a gap. Eventually you will come to a range with two entries with a hole in the middle.
The time complexity of this is O(log N). Contrast to a linear scan, whose worst case is O(N).
Based on the approach suggested by #phs above, here is the C code to do that:
#include <stdio.h>
int find_missing_number(int arr[], int len) {
int first, middle, last;
first = 0;
last = len - 1;
middle = (first + last)/2;
while (first < last) {
if ((arr[middle] - arr[first]) != (middle - first)) {
/* there is a hole in the first half */
if ((middle - first) == 1 && (arr[middle] - arr[first] > 1)) {
return (arr[middle] - 1);
}
last = middle;
} else if ((arr[last] - arr[middle]) != (last - middle)) {
/* there is a hole in the second half */
if ((last - middle) == 1 && (arr[last] - arr[middle] > 1)) {
return (arr[middle] + 1);
}
first = middle;
} else {
/* there is no hole */
return -1;
}
middle = (first + last)/2;
}
/* there is no hole */
return -1;
}
int main() {
int arr[] = {3, 5, 1};
printf("%d", find_missing_number(arr, sizeof arr/(sizeof arr[0]))); /* prints 4 */
return 0;
}
Since numbers from 0 to n - 1 are sorted in an array, the first numbers should be same as their indexes. That's to say, the number 0 is located at the cell with index 0, the number 1 is located at the cell with index 1, and so on. If the missing number is denoted as m. Numbers less then m are located at cells with indexes same as values.
The number m + 1 is located at a cell with index m, The number m + 2 is located at a cell with index m + 1, and so on. We can see that, the missing number m is the first cell whose value is not identical to its value.
Therefore, it is required to search in an array to find the first cell whose value is not identical to its value. Since the array is sorted, we could find it in O(lg n) time based on the binary search algorithm as implemented below:
int getOnceNumber_sorted(int[] numbers)
{
int length = numbers.length
int left = 0;
int right = length - 1;
while(left <= right)
{
int middle = (right + left) >> 1;
if(numbers[middle] != middle)
{
if(middle == 0 || numbers[middle - 1] == middle - 1)
return middle;
right = middle - 1;
}
else
left = middle + 1;
}
return -1;
}
This solution is borrowed from my blog: http://codercareer.blogspot.com/2013/02/no-37-missing-number-in-array.html.
Based on algorithm provided by #phs
int findFirstMissing(int array[], int start , int end){
if(end<=start+1){
return start+1;
}
else{
int mid = start + (end-start)/2;
if((array[mid] - array[start]) != (mid-start))
return findFirstMissing(array, start, mid);
else
return findFirstMissing(array, mid+1, end);
}
}
Below is my solution, which I believe is simple and avoids an excess number of confusing if-statements. It also works when you don't start at 0 or have negative numbers involved! The complexity is O(lg(n)) time with O(1) space, assuming the client owns the array of numbers (otherwise it's O(n)).
The Algorithm in C Code
int missingNumber(int a[], int size) {
int lo = 0;
int hi = size - 1;
// TODO: Use this if we need to ensure we start at 0!
//if(a[0] != 0) { return 0; }
// All elements present? If so, return next largest number.
if((hi-lo) == (a[hi]-a[lo])) { return a[hi]+1; }
// While 2 or more elements to left to consider...
while((hi-lo) >= 2) {
int mid = (lo + hi) / 2;
if((mid-lo) != (a[mid]-a[lo])) { // Explore left-hand side
hi = mid;
} else { // Explore right hand side
lo = mid + 1;
}
}
// Return missing value from the two candidates remaining...
return (lo == (a[lo]-a[0])) ? hi + a[0] : lo + a[0];
}
Test Outputs
int a[] = {0}; // Returns: 1
int a[] = {1}; // Returns: 2
int a[] = {0, 1}; // Returns: 2
int a[] = {1, 2}; // Returns: 3
int a[] = {0, 2}; // Returns: 1
int a[] = {0, 2, 3, 4}; // Returns: 1
int a[] = {0, 1, 2, 4}; // Returns: 3
int a[] = {0, 1, 2, 4, 5, 6, 7, 8, 9}; // Returns: 3
int a[] = {2, 3, 5, 6, 7, 8, 9}; // Returns: 4
int a[] = {2, 3, 4, 5, 6, 8, 9}; // Returns: 7
int a[] = {-3, -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // Returns: -1
int a[] = {-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // Returns: 10
The general procedure is:
(Optional) Check if the array starts at 0. If it doesn't, return 0 as missing.
Check if the array of integers is complete with no missing integer. If it is not missing an integer, return the next largest integer.
In a binary search fashion, check for a mismatch between the difference in the indices and array values. A mismatch tells us which half a missing element is in. If there is a mismatch in the first half, move left, otherwise move right. Do this until you have two candidate elements left to consider.
Return the number that is missing based on incorrect candidate.
Note, the algorithm's assumptions are:
First and last elements are considered to never be missing. These elements establish a range.
Only one integer is ever missing in the array. This will not find more than one missing integer!
Integer in the array are expected to increase in steps of 1, not at any other rate.
Have you considered a run-length encoding? That is, you encode the first number as well as the count of numbers that follow it consecutively. Not only can you represent the numbers used very efficiently this way, the first hole will be at the end of the first run-length encoded segment.
To illustrate with your example:
[0, 1, 2, 4, 6]
Would be encoded as:
[0:3, 4:1, 6:1]
Where x:y means there is a set of numbers consecutively starting at x for y numbers in a row. This tells us immediately that the first gap is at location 3. Note, however, that this will be much more efficient when the assigned addresses are clustered together, not randomly dispersed throughout the range.
if the list is sorted, I'd iterate over the list and do something like this Python code:
missing = []
check = 0
for n in numbers:
if n > check:
# all the numbers in [check, n) were not present
missing += range(check, n)
check = n + 1
# now we account for any missing numbers after the last element of numbers
if check < MAX:
missing += range(check, MAX + 1)
if lots of numbers are missing, you might want to use #Nathan's run-length encoding suggestion for the missing list.
Missing
Number=(1/2)(n)(n+1)-(Sum of all elements in the array)
Here n is the size of array+1.
Array: [1,2,3,4,5,6,8,9]
Index: [0,1,2,3,4,5,6,7]
int findMissingEmementIndex(int a[], int start, int end)
{
int mid = (start + end)/2;
if( Math.abs(a[mid] - a[start]) != Math.abs(mid - start) ){
if( Math.abs(mid - start) == 1 && Math.abs(a[mid] - a[start])!=1 ){
return start +1;
}
else{
return findMissingElmementIndex(a,start,mid);
}
}
else if( a[mid] - a[end] != end - start){
if( Math.abs(end - mid) ==1 && Math.abs(a[end] - a[mid])!=1 ){
return mid +1;
}
else{
return findMissingElmementIndex(a,mid,end);
}
}
else{
return No_Problem;
}
}
This is an interview Question. We will have an array of more than one missing numbers and we will put all those missing numbers in an ArrayList.
public class Test4 {
public static void main(String[] args) {
int[] a = { 1, 3, 5, 7, 10 };
List<Integer> list = new ArrayList<>();
int start = 0;
for (int i = 0; i < a.length; i++) {
int ch = a[i];
if (start == ch) {
start++;
} else {
list.add(start);
start++;
i--; // a must do.
} // else
} // for
System.out.println(list);
}
}
Functional Programming solution (Scala)
Nice and elegant
Lazy evaluation
def gapFinder(sortedList: List[Int], start: Int = 0): Int = {
def withGuards: Stream[Int] =
(start - 1) +: sortedList.toStream :+ (sortedList.last + 2)
if (sortedList.isEmpty) start
else withGuards.sliding(2)
.dropWhile { p => p.head + 1 >= p.last }.next()
.headOption.getOrElse(start) + 1
} // 8-line solution
// Tests
assert(gapFinder(List()) == 0)
assert(gapFinder(List[Int](0)) == 1)
assert(gapFinder(List[Int](1)) == 0)
assert(gapFinder(List[Int](2)) == 0)
assert(gapFinder(List[Int](0, 1, 2)) == 3)
assert(gapFinder(List[Int](0, 2, 4)) == 1)
assert(gapFinder(List[Int](0, 1, 2, 4)) == 3)
assert(gapFinder(List[Int](0, 1, 2, 4, 5)) == 3)
import java.util.Scanner;
class MissingNumber {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int[] arr =new int[n];
for (int i=0;i<n;i++){
arr[i]=scan.nextInt();
}
for (int i=0;i<n;i++){
if(arr[i+1]==arr[i]+1){
}
else{
System.out.println(arr[i]+1);
break;
}
}
}
}
I was looking for a super simple way to find the first missing number in a sorted array with a max potential value in javascript and didn't have to worry about efficiency too much as I didn't plan on using a list longer 10-20 items at the most. This is the recursive function I came up with:
function findFirstMissingNumber(sortedList, index, x, maxAllowedValue){
if(sortedList[index] == x && x < maxAllowedValue){
return findFirstMissingNumber(sortedList, (index+1), (x+1), maxAllowedValue);
}else{ return x; }
}
findFirstMissingNumber([3, 4, 5, 7, 8, 9], 0, 3, 10);
//expected output: 6
Give it your array, the index you wish to start at, the value you expect it to be and the maximum value you'd like to check up to.
i got one algorithm for finding the missing number in the sorted list. its complexity is logN.
public int execute2(int[] array) {
int diff = Math.min(array[1]-array[0], array[2]-array[1]);
int min = 0, max = arr.length-1;
boolean missingNum = true;
while(min<max) {
int mid = (min + max) >>> 1;
int leftDiff = array[mid] - array[min];
if(leftDiff > diff * (mid - min)) {
if(mid-min == 1)
return (array[mid] + array[min])/2;
max = mid;
missingNum = false;
continue;
}
int rightDiff = array[max] - array[mid];
if(rightDiff > diff * (max - mid)) {
if(max-mid == 1)
return (array[max] + array[mid])/2;
min = mid;
missingNum = false;
continue;
}
if(missingNum)
break;
}
return -1;
}
Based on algorithm provided by #phs
public class Solution {
public int missing(int[] array) {
// write your solution here
if(array == null){
return -1;
}
if (array.length == 0) {
return 1;
}
int left = 0;
int right = array.length -1;
while (left < right - 1) {
int mid = left + (right - left) / 2;
if (array[mid] - array[left] != mid - left) { //there is gap in [left, mid]
right = mid;
}else if (array[right] - array[mid] != right - mid) { //there is gap in [mid, right]
left = mid;
}else{ //there is no gapin [left, right], which means the missing num is the at 0 and N
return array[0] == 1 ? array.length + 1 : 1 ;
}
}
if (array[right] - array[left] == 2){ //missing number is between array[left] and array[right]
return left + 2;
}else{
return array[0] == 1 ? -1 : 1; //when ther is only one element in array
}
}
}
public static int findFirst(int[] arr) {
int l = -1;
int r = arr.length;
while (r - l > 1) {
int middle = (r + l) / 2;
if (arr[middle] > middle) {
r = middle;
}
l = middle;
}
return r;
}

Finding maximum for every window of size k in an array

Given an array of size n and k, how do you find the maximum for every contiguous subarray of size k?
For example
arr = 1 5 2 6 3 1 24 7
k = 3
ans = 5 6 6 6 24 24
I was thinking of having an array of size k and each step evict the last element out and add the new element and find maximum among that. It leads to a running time of O(nk). Is there a better way to do this?
You have heard about doing it in O(n) using dequeue.
Well that is a well known algorithm for this question to do in O(n).
The method i am telling is quite simple and has time complexity O(n).
Your Sample Input:
n=10 , W = 3
10 3
1 -2 5 6 0 9 8 -1 2 0
Answer = 5 6 6 9 9 9 8 2
Concept: Dynamic Programming
Algorithm:
N is number of elements in an array and W is window size. So, Window number = N-W+1
Now divide array into blocks of W starting from index 1.
Here divide into blocks of size 'W'=3.
For your sample input:
We have divided into blocks because we will calculate maximum in 2 ways A.) by traversing from left to right B.) by traversing from right to left.
but how ??
Firstly, Traversing from Left to Right. For each element ai in block we will find maximum till that element ai starting from START of Block to END of that block.
So here,
Secondly, Traversing from Right to Left. For each element 'ai' in block we will find maximum till that element 'ai' starting from END of Block to START of that block.
So Here,
Now we have to find maximum for each subarray or window of size 'W'.
So, starting from index = 1 to index = N-W+1 .
max_val[index] = max(RL[index], LR[index+w-1]);
for index=1: max_val[1] = max(RL[1],LR[3]) = max(5,5)= 5
Simliarly, for all index i, (i<=(n-k+1)), value at RL[i] and LR[i+w-1]
are compared and maximum among those two is answer for that subarray.
So Final Answer : 5 6 6 9 9 9 8 2
Time Complexity: O(n)
Implementation code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LIM 100001
using namespace std;
int arr[LIM]; // Input Array
int LR[LIM]; // maximum from Left to Right
int RL[LIM]; // maximum from Right to left
int max_val[LIM]; // number of subarrays(windows) will be n-k+1
int main(){
int n, w, i, k; // 'n' is number of elements in array
// 'w' is Window's Size
cin >> n >> w;
k = n - w + 1; // 'K' is number of Windows
for(i = 1; i <= n; i++)
cin >> arr[i];
for(i = 1; i <= n; i++){ // for maximum Left to Right
if(i % w == 1) // that means START of a block
LR[i] = arr[i];
else
LR[i] = max(LR[i - 1], arr[i]);
}
for(i = n; i >= 1; i--){ // for maximum Right to Left
if(i == n) // Maybe the last block is not of size 'W'.
RL[i] = arr[i];
else if(i % w == 0) // that means END of a block
RL[i] = arr[i];
else
RL[i] = max(RL[i+1], arr[i]);
}
for(i = 1; i <= k; i++) // maximum
max_val[i] = max(RL[i], LR[i + w - 1]);
for(i = 1; i <= k ; i++)
cout << max_val[i] << " ";
cout << endl;
return 0;
}
Running Code Link
I'll try to proof: (by #johnchen902)
If k % w != 1 (k is not the begin of a block)
Let k* = The begin of block containing k
ans[k] = max( arr[k], arr[k + 1], arr[k + 2], ..., arr[k + w - 1])
= max( max( arr[k], arr[k + 1], arr[k + 2], ..., arr[k*]),
max( arr[k*], arr[k* + 1], arr[k* + 2], ..., arr[k + w - 1]) )
= max( RL[k], LR[k+w-1] )
Otherwise (k is the begin of a block)
ans[k] = max( arr[k], arr[k + 1], arr[k + 2], ..., arr[k + w - 1])
= RL[k] = LR[k+w-1]
= max( RL[k], LR[k+w-1] )
Dynamic programming approach is very neatly explained by Shashank Jain. I would like to explain how to do the same using dequeue.
The key is to maintain the max element at the top of the queue(for a window ) and discarding the useless elements and we also need to discard the elements that are out of index of current window.
useless elements = If Current element is greater than the last element of queue than the last element of queue is useless .
Note : We are storing the index in queue not the element itself. It will be more clear from the code itself.
1. If Current element is greater than the last element of queue than the last element of queue is useless . We need to delete that last element.
(and keep deleting until the last element of queue is smaller than current element).
2. If if current_index - k >= q.front() that means we are going out of window so we need to delete the element from front of queue.
vector<int> max_sub_deque(vector<int> &A,int k)
{
deque<int> q;
for(int i=0;i<k;i++)
{
while(!q.empty() && A[i] >= A[q.back()])
q.pop_back();
q.push_back(i);
}
vector<int> res;
for(int i=k;i<A.size();i++)
{
res.push_back(A[q.front()]);
while(!q.empty() && A[i] >= A[q.back()] )
q.pop_back();
while(!q.empty() && q.front() <= i-k)
q.pop_front();
q.push_back(i);
}
res.push_back(A[q.front()]);
return res;
}
Since each element is enqueued and dequeued atmost 1 time to time complexity is O(n+n) = O(2n) = O(n).
And the size of queue can not exceed the limit k . so space complexity = O(k).
An O(n) time solution is possible by combining the two classic interview questions:
Make a stack data-structure (called MaxStack) which supports push, pop and max in O(1) time.
This can be done using two stacks, the second one contains the minimum seen so far.
Model a queue with a stack.
This can done using two stacks. Enqueues go into one stack, and dequeues come from the other.
For this problem, we basically need a queue, which supports enqueue, dequeue and max in O(1) (amortized) time.
We combine the above two, by modelling a queue with two MaxStacks.
To solve the question, we queue k elements, query the max, dequeue, enqueue k+1 th element, query the max etc. This will give you the max for every k sized sub-array.
I believe there are other solutions too.
1)
I believe the queue idea can be simplified. We maintain a queue and a max for every k. We enqueue a new element, and dequeu all elements which are not greater than the new element.
2) Maintain two new arrays which maintain the running max for each block of k, one array for one direction (left to right/right to left).
3) Use a hammer: Preprocess in O(n) time for range maximum queries.
The 1) solution above might be the most optimal.
You need a fast data structure that can add, remove and query for the max element in less than O(n) time (you can just use an array if O(n) or O(nlogn) is acceptable). You can use a heap, a balanced binary search tree, a skip list, or any other sorted data structure that performs these operations in O(log(n)).
The good news is that most popular languages have a sorted data structure implemented that supports these operations for you. C++ has std::set and std::multiset (you probably need the latter) and Java has PriorityQueue and TreeSet.
Here is the java implementation
public static Integer[] maxsInEveryWindows(int[] arr, int k) {
Deque<Integer> deque = new ArrayDeque<Integer>();
/* Process first k (or first window) elements of array */
for (int i = 0; i < k; i++) {
// For very element, the previous smaller elements are useless so
// remove them from deque
while (!deque.isEmpty() && arr[i] >= arr[deque.peekLast()]) {
deque.removeLast(); // Remove from rear
}
// Add new element at rear of queue
deque.addLast(i);
}
List<Integer> result = new ArrayList<Integer>();
// Process rest of the elements, i.e., from arr[k] to arr[n-1]
for (int i = k; i < arr.length; i++) {
// The element at the front of the queue is the largest element of
// previous window, so add to result.
result.add(arr[deque.getFirst()]);
// Remove all elements smaller than the currently
// being added element (remove useless elements)
while (!deque.isEmpty() && arr[i] >= arr[deque.peekLast()]) {
deque.removeLast();
}
// Remove the elements which are out of this window
while (!deque.isEmpty() && deque.getFirst() <= i - k) {
deque.removeFirst();
}
// Add current element at the rear of deque
deque.addLast(i);
}
// Print the maximum element of last window
result.add(arr[deque.getFirst()]);
return result.toArray(new Integer[0]);
}
Here is the corresponding test case
#Test
public void maxsInWindowsOfSizeKTest() {
Integer[] result = ArrayUtils.maxsInEveryWindows(new int[]{1, 2, 3, 1, 4, 5, 2, 3, 6}, 3);
assertThat(result, equalTo(new Integer[]{3, 3, 4, 5, 5, 5, 6}));
result = ArrayUtils.maxsInEveryWindows(new int[]{8, 5, 10, 7, 9, 4, 15, 12, 90, 13}, 4);
assertThat(result, equalTo(new Integer[]{10, 10, 10, 15, 15, 90, 90}));
}
Using a heap (or tree), you should be able to do it in O(n * log(k)). I'm not sure if this would be indeed better.
here is the Python implementation in O(1)...Thanks to #Shahshank Jain in advance..
from sys import stdin,stdout
from operator import *
n,w=map(int , stdin.readline().strip().split())
Arr=list(map(int , stdin.readline().strip().split()))
k=n-w+1 # window size = k
leftA=[0]*n
rightA=[0]*n
result=[0]*k
for i in range(n):
if i%w==0:
leftA[i]=Arr[i]
else:
leftA[i]=max(Arr[i],leftA[i-1])
for i in range(n-1,-1,-1):
if i%w==(w-1) or i==n-1:
rightA[i]=Arr[i]
else:
rightA[i]=max(Arr[i],rightA[i+1])
for i in range(k):
result[i]=max(rightA[i],leftA[i+w-1])
print(*result,sep=' ')
Method 1: O(n) time, O(k) space
We use a deque (it is like a list but with constant-time insertion and deletion from both ends) to store the index of useful elements.
The index of the current max is kept at the leftmost element of deque. The rightmost element of deque is the smallest.
In the following, for easier explanation we say an element from the array is in the deque, while in fact the index of that element is in the deque.
Let's say {5, 3, 2} are already in the deque (again, if fact their indexes are).
If the next element we read from the array is bigger than 5 (remember, the leftmost element of deque holds the max), say 7: We delete the deque and create a new one with only 7 in it (we do this because the current elements are useless, we have found a new max).
If the next element is less than 2 (which is the smallest element of deque), say 1: We add it to the right ({5, 3, 2, 1})
If the next element is bigger than 2 but less than 5, say 4: We remove elements from right that are smaller than the element and then add the element from right ({5, 4}).
Also we keep elements of the current window only (we can do this in constant time because we are storing the indexes instead of elements).
from collections import deque
def max_subarray(array, k):
deq = deque()
for index, item in enumerate(array):
if len(deq) == 0:
deq.append(index)
elif index - deq[0] >= k: # the max element is out of the window
deq.popleft()
elif item > array[deq[0]]: # found a new max
deq = deque()
deq.append(index)
elif item < array[deq[-1]]: # the array item is smaller than all the deque elements
deq.append(index)
elif item > array[deq[-1]] and item < array[deq[0]]:
while item > array[deq[-1]]:
deq.pop()
deq.append(index)
if index >= k - 1: # start printing when the first window is filled
print(array[deq[0]])
Proof of O(n) time: The only part we need to check is the while loop. In the whole runtime of the code, the while loop can perform at most O(n) operations in total. The reason is that the while loop pops elements from the deque, and since in other parts of the code, we do at most O(n) insertions into the deque, the while loop cannot exceed O(n) operations in total. So the total runtime is O(n) + O(n) = O(n)
Method 2: O(n) time, O(n) space
This is the explanation of the method suggested by S Jain (as mentioned in the comments of his post, this method doesn't work with data streams, which most sliding window questions are designed for).
The reason that method works is explained using the following example:
array = [5, 6, 2, 3, 1, 4, 2, 3]
k = 4
[5, 6, 2, 3 1, 4, 2, 3 ]
LR: 5 6 6 6 1 4 4 4
RL: 6 6 3 3 4 4 3 3
6 6 4 4 4
To get the max for the window [2, 3, 1, 4],
we can get the max of [2, 3] and max of [1, 4], and return the bigger of the two.
Max of [2, 3] is calculated in the RL pass and max of [1, 4] is calculated in LR pass.
Using Fibonacci heap, you can do it in O(n + (n-k) log k), which is equal to O(n log k) for small k, for k close to n this becomes O(n).
The algorithm: in fact, you need:
n inserts to the heap
n-k deletions
n-k findmax's
How much these operations cost in Fibonacci heaps? Insert and findmax is O(1) amortized, deletion is O(log n) amortized. So, we have
O(n + (n-k) log k + (n-k)) = O(n + (n-k) log k)
Sorry, this should have been a comment but I am not allowed to comment for now.
#leo and #Clay Goddard
You can save yourselves from re-computing the maximum by storing both maximum and 2nd maximum of the window in the beginning
(2nd maximum will be the maximum only if there are two maximums in the initial window). If the maximum slides out of the window you still have the next best candidate to compare with the new entry. So you get O(n) , otherwise if you allowed the whole re-computation again the worst case order would be O(nk), k is the window size.
class MaxFinder
{
// finds the max and its index
static int[] findMaxByIteration(int arr[], int start, int end)
{
int max, max_ndx;
max = arr[start];
max_ndx = start;
for (int i=start; i<end; i++)
{
if (arr[i] > max)
{
max = arr[i];
max_ndx = i;
}
}
int result[] = {max, max_ndx};
return result;
}
// optimized to skip iteration, when previous windows max element
// is present in current window
static void optimizedPrintKMax(int arr[], int n, int k)
{
int i, j, max, max_ndx;
// for first window - find by iteration.
int result[] = findMaxByIteration(arr, 0, k);
System.out.printf("%d ", result[0]);
max = result[0];
max_ndx = result[1];
for (j=1; j <= (n-k); j++)
{
// if previous max has fallen out of current window, iterate and find
if (max_ndx < j)
{
result = findMaxByIteration(arr, j, j+k);
max = result[0];
max_ndx = result[1];
}
// optimized path, just compare max with new_elem that has come into the window
else
{
int new_elem_ndx = j + (k-1);
if (arr[new_elem_ndx] > max)
{
max = arr[new_elem_ndx];
max_ndx = new_elem_ndx;
}
}
System.out.printf("%d ", max);
}
}
public static void main(String[] args)
{
int arr[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
//int arr[] = {1,5,2,6,3,1,24,7};
int n = arr.length;
int k = 3;
optimizedPrintKMax(arr, n, k);
}
}
package com;
public class SlidingWindow {
public static void main(String[] args) {
int[] array = { 1, 5, 2, 6, 3, 1, 24, 7 };
int slide = 3;//say
List<Integer> result = new ArrayList<Integer>();
for (int i = 0; i < array.length - (slide-1); i++) {
result.add(getMax(array, i, slide));
}
System.out.println("MaxList->>>>" + result.toString());
}
private static Integer getMax(int[] array, int i, int slide) {
List<Integer> intermediate = new ArrayList<Integer>();
System.out.println("Initial::" + intermediate.size());
while (intermediate.size() < slide) {
intermediate.add(array[i]);
i++;
}
Collections.sort(intermediate);
return intermediate.get(slide - 1);
}
}
Here is the solution in O(n) time complexity with auxiliary deque
public class TestSlidingWindow {
public static void main(String[] args) {
int[] arr = { 1, 5, 7, 2, 1, 3, 4 };
int k = 3;
printMaxInSlidingWindow(arr, k);
}
public static void printMaxInSlidingWindow(int[] arr, int k) {
Deque<Integer> queue = new ArrayDeque<Integer>();
Deque<Integer> auxQueue = new ArrayDeque<Integer>();
int[] resultArr = new int[(arr.length - k) + 1];
int maxElement = 0;
int j = 0;
for (int i = 0; i < arr.length; i++) {
queue.add(arr[i]);
if (arr[i] > maxElement) {
maxElement = arr[i];
}
/** we need to maintain the auxiliary deque to maintain max element in case max element is removed.
We add the element to deque straight away if subsequent element is less than the last element
(as there is a probability if last element is removed this element can be max element) otherwise
remove all lesser element then insert current element **/
if (auxQueue.size() > 0) {
if (arr[i] < auxQueue.peek()) {
auxQueue.push(arr[i]);
} else {
while (auxQueue.size() > 0 && (arr[i] > auxQueue.peek())) {
auxQueue.pollLast();
}
auxQueue.push(arr[i]);
}
}else {
auxQueue.push(arr[i]);
}
if (queue.size() > 3) {
int removedEl = queue.removeFirst();
if (maxElement == removedEl) {
maxElement = auxQueue.pollFirst();
}
}
if (queue.size() == 3) {
resultArr[j++] = maxElement;
}
}
for (int i = 0; i < resultArr.length; i++) {
System.out.println(resultArr[i]);
}
}
}
static void countDistinct(int arr[], int n, int k)
{
System.out.print("\nMaximum integer in the window : ");
// Traverse through every window
for (int i = 0; i <= n - k; i++) {
System.out.print(findMaximuminAllWindow(Arrays.copyOfRange(arr, i, arr.length), k)+ " ");
}
}
private static int findMaximuminAllWindow(int[] win, int k) {
// TODO Auto-generated method stub
int max= Integer.MIN_VALUE;
for(int i=0; i<k;i++) {
if(win[i]>max)
max=win[i];
}
return max;
}
arr = 1 5 2 6 3 1 24 7
We have to find the maximum of subarray, Right?
So, What is meant by subarray?
SubArray = Partial set and it should be in order and contiguous.
From the above array
{1,5,2} {6,3,1} {1,24,7} all are the subarray examples
n = 8 // Array length
k = 3 // window size
For finding the maximum, we have to iterate through the array, and find the maximum.
From the window size k,
{1,5,2} = 5 is the maximum
{5,2,6} = 6 is the maximum
{2,6,3} = 6 is the maximum
and so on..
ans = 5 6 6 6 24 24
It can be evaluated as the n-k+1
Hence, 8-3+1 = 6
And the length of an answer is 6 as we seen.
How can we solve this now?
When the data is moving from the pipe, the first thought for the data structure came in mind is the Queue
But, rather we are not discussing much here, we directly jump on the deque
Thinking Would be:
Window is fixed and data is in and out
Data is fixed and window is sliding
EX: Time series database
While (Queue is not empty and arr[Queue.back() < arr[i]] {
Queue.pop_back();
Queue.push_back();
For the rest:
Print the front of queue
// purged expired element
While (queue not empty and queue.front() <= I-k) {
Queue.pop_front();
While (Queue is not empty and arr[Queue.back() < arr[i]] {
Queue.pop_back();
Queue.push_back();
}
}
arr = [1, 2, 3, 1, 4, 5, 2, 3, 6]
k = 3
for i in range(len(arr)-k):
k=k+1
print (max(arr[i:k]),end=' ') #3 3 4 5 5 5 6
Two approaches.
Segment Tree O(nlog(n-k))
Build a maximum segment-tree.
Query between [i, i+k)
Something like..
public static void printMaximums(int[] a, int k) {
int n = a.length;
SegmentTree tree = new SegmentTree(a);
for (int i=0; i<=n-k; i++) System.out.print(tree.query(i, i+k));
}
Deque O(n)
If the next element is greater than the rear element, remove the rear element.
If the element in the front of the deque is out of the window, remove the front element.
public static void printMaximums(int[] a, int k) {
int n = a.length;
Deque<int[]> deck = new ArrayDeque<>();
List<Integer> result = new ArrayList<>();
for (int i=0; i<n; i++) {
while (!deck.isEmpty() && a[i] >= deck.peekLast()[0]) deck.pollLast();
deck.offer(new int[] {a[i], i});
while (!deck.isEmpty() && deck.peekFirst()[1] <= i - k) deck.pollFirst();
if (i >= k - 1) result.add(deck.peekFirst()[0]);
}
System.out.println(result);
}
Here is an optimized version of the naive (conditional) nested loop approach I came up with which is much faster and doesn't require any auxiliary storage or data structure.
As the program moves from window to window, the start index and end index moves forward by 1. In other words, two consecutive windows have adjacent start and end indices.
For the first window of size W , the inner loop finds the maximum of elements with index (0 to W-1). (Hence i == 0 in the if in 4th line of the code).
Now instead of computing for the second window which only has one new element, since we have already computed the maximum for elements of indices 0 to W-1, we only need to compare this maximum to the only new element in the new window with the index W.
But if the element at 0 was the maximum which is the only element not part of the new window, we need to compute the maximum using the inner loop from 1 to W again using the inner loop (hence the second condition maxm == arr[i-1] in the if in line 4), otherwise just compare the maximum of the previous window and the only new element in the new window.
void print_max_for_each_subarray(int arr[], int n, int k)
{
int maxm;
for(int i = 0; i < n - k + 1 ; i++)
{
if(i == 0 || maxm == arr[i-1]) {
maxm = arr[i];
for(int j = i+1; j < i+k; j++)
if(maxm < arr[j]) maxm = arr[j];
}
else {
maxm = maxm < arr[i+k-1] ? arr[i+k-1] : maxm;
}
cout << maxm << ' ';
}
cout << '\n';
}
You can use Deque data structure to implement this. Deque has an unique facility that you can insert and remove elements from both the ends of the queue unlike the traditional queue where you can only insert from one end and remove from other.
Following is the code for the above problem.
public int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length;
int[] maxInWindow = new int[n - k + 1];
Deque<Integer> dq = new LinkedList<Integer>();
int i = 0;
for(; i<k; i++){
while(!dq.isEmpty() && nums[dq.peekLast()] <= nums[i]){
dq.removeLast();
}
dq.addLast(i);
}
for(; i <n; i++){
maxInWindow[i - k] = nums[dq.peekFirst()];
while(!dq.isEmpty() && dq.peekFirst() <= i - k){
dq.removeFirst();
}
while(!dq.isEmpty() && nums[dq.peekLast()] <= nums[i]){
dq.removeLast();
}
dq.addLast(i);
}
maxInWindow[i - k] = nums[dq.peekFirst()];
return maxInWindow;
}
the resultant array will have n - k + 1 elements where n is length of the given array, k is the given window size.
We can solve it using the Python , applying the slicing.
def sliding_window(a,k,n):
max_val =[]
val =[]
val1=[]
for i in range(n-k-1):
if i==0:
val = a[0:k+1]
print("The value in val variable",val)
val1 = max(val)
max_val.append(val1)
else:
val = a[i:i*k+1]
val1 =max(val)
max_val.append(val1)
return max_val
Driver Code
a = [15,2,3,4,5,6,2,4,9,1,5]
n = len(a)
k = 3
sl=s liding_window(a,k,n)
print(sl)
Create a TreeMap of size k. Put first k elements as keys in it and assign any value like 1(doesn't matter). TreeMap has the property to sort the elements based on key so now, first element in map will be min and last element will be max element. Then remove 1 element from the map whose index in the arr is i-k. Here, I have considered that Input elements are taken in array arr and from that array we are filling the map of size k. Since, we can't do anything with sorting happening inside TreeMap, therefore this approach will also take O(n) time.
100% working Tested (Swift)
func maxOfSubArray(arr:[Int],n:Int,k:Int)->[Int]{
var lenght = arr.count
var resultArray = [Int]()
for i in 0..<arr.count{
if lenght+1 > k{
let tempArray = Array(arr[i..<k+i])
resultArray.append(tempArray.max()!)
}
lenght = lenght - 1
}
print(resultArray)
return resultArray
}
This way we can use:
maxOfSubArray(arr: [1,2,3,1,4,5,2,3,6], n: 9, k: 3)
Result:
[3, 3, 4, 5, 5, 5, 6]
Just notice that you only have to find in the new window if:
* The new element in the window is smaller than the previous one (if it's bigger, it's for sure this one).
OR
* The element that just popped out of the window was the current bigger.
In this case, re-scan the window.
for how big k? for reasonable-sized k. you can create k k-sized buffers and just iterate over the array keeping track of max element pointers in the buffers - needs no data structures and is O(n) k^2 pre-allocation.
A complete working solution in Amortised Constant O(1) Complexity.
https://github.com/varoonverma/code-challenge.git
Compare the first k elements and find the max, this is your first number
then compare the next element to the previous max. If the next element is bigger, that is your max of the next subarray, if its equal or smaller, the max for that sub array is the same
then move on to the next number
max(1 5 2) = 5
max(5 6) = 6
max(6 6) = 6
... and so on
max(3 24) = 24
max(24 7) = 24
It's only slightly better than your answer

What is the more efficient algorithm to equalize a vector?

Given a vector of n elements of type integer, what is the more efficient algorithm that produce the minimum number of transformation step resulting in a vector that have all its elements equals, knowing that :
in a single step, you could transfer at most one point from element to its neighbours ([0, 3, 0] -> [1, 2, 0] is ok but not [0, 3, 0] -> [1, 1, 1]).
in a single step, an element could receive 2 points : one from its left neighbour and one from the right ([3, 0 , 3] -> [2, 2, 2]).
first element and last element have only one neighbour, respectively, the 2nd element and the n-1 element.
an element cannot be negative at any step.
Examples :
Given :
0, 3, 0
Then 2 steps are required :
1, 2, 0
1, 1, 1
Given :
3, 0, 3
Then 1 step is required :
2, 2, 2
Given :
4, 0, 0, 0, 4, 0, 0, 0
Then 3 steps are required :
3, 1, 0, 0, 3, 1, 0, 0
2, 1, 1, 0, 2, 1, 1, 0
1, 1, 1; 1, 1, 1, 1, 1
My current algorithm is based on the sums of the integers at each side of an element. But I'm not sure if it produce the minimum steps.
FYI the problem is part of a code contest (created by Criteo http://codeofduty.criteo.com) that is over.
Here is a way. You know the sum of the array, so you know the target number in each cell.
Thus you also know the target sum for each subarray.
Then iterate through the array and on each step you make a desicion:
Move 1 to the left: if the sum up to the previous element is less then desired.
Move 1 to the right: if the sum up to the current element is more than desired
Don't do anything: if both of the above are false
Repeat this until no more changes are made (i.e. you only applied 3 for each of the elements).
public static int F(int[] ar)
{
int iter = -1;
bool finished = false;
int total = ar.Sum();
if (ar.Length == 0 || total % ar.Length != 0) return 0; //can't do it
int target = total / ar.Length;
int sum = 0;
while (!finished)
{
iter++;
finished = true;
bool canMoveNext = true;
//first element
if (ar[0] > target)
{
finished = false;
ar[0]--;
ar[1]++;
canMoveNext = ar[1] != 1;
}
sum = ar[0];
for (int i = 1; i < ar.Length; i++)
{
if (!canMoveNext)
{
canMoveNext = true;
sum += ar[i];
continue;
}
if (sum < i * target && ar[i] > 0)
{
finished = false;
ar[i]--;
ar[i - 1]++;
sum++;
}
else if (sum + ar[i] > (i + 1) * target && ar[i] > 0) //this can't happen for the last element so we are safe
{
finished = false;
ar[i]--;
ar[i + 1]++;
canMoveNext = ar[i + 1] != 1;
}
sum += ar[i];
}
}
return iter;
}
I've got an idea. I'm not sure it produces the optimal result, but it feels like it can.
Suppose the initial vector is the N-sized vector V. You need two additional N-sized vector :
In the L vector, you sum elements starting from the left : L[n] = sum(i=0;i<=n) V[n]
In the R vector, you sum elements starting from the right: R[n] = sum(i=n;i<N) V[n]
You finally need one last specific value : the sum of all the elements of V is supposed to be equal to k*N with k an integer. And you have L[N-1] == R[0] == k*N
Let's take the L vector. The idea is that for any n, consider the V vector divided in two parts, one from 0 to n, and the other contains the rest. If L[n]<n*k, then you've got to "fill" the first part with values from the second part. And vice versa if L[n]>n*k. If L[i]==i*k, then congratulations, the problem can be subdivided in two subproblems! There is no reason for any value from the second vector to be transferred to the first vector, and vice-versa.
Then, the algorithm is simple : for every value of n, check the value of L[n]-n*k and R[n]-(N-n)*k and act accordingly. There is just one special case, if L[n]-n*k>0 and R[n]-(N-n)*k>0 (there is a high value at V[n]), you must empty it in both directions. Just choose at random a direction to tranfer.
Of course, don't forget to update L and R accordingly.
Edit : In fact, it seems that you only need the L vector. Here is a simplified algorithm.
If L[n]==n*k, don't do anything
If L[n]<n*k, then transfer one value from V[n+1] to V[n] (if V[n+1]>0 of course)
If L[n]>n*k, then transfer one value from V[n] to V[n+1] (if V[n]>0 of course)
And (the special case) if you're asked to tranfer from V[n] to V[n-1] and V[n+1], just tranfer randomly once, it won't change the final result.
Thanks to Sam Hocevar, for the following alternative implementation to the fiver's one :
public static int F(int[] ar)
{
int total = ar.Sum();
if (ar.Length == 0 || total % ar.Length != 0) return 0; //can't do it
int target = total / ar.Length;
int[] left = new int[ar.Length];
int[] right = new int[ar.Length];
int maxshifts = 0;
int delta = 0;
for (int i = 0; i < ar.Length; i++)
{
left[i] = delta < 0 ? -delta : 0;
delta += ar[i] - target;
right[i] = delta > 0 ? delta : 0;
if (left[i] + right[i] > maxshifts) {
maxshifts = left[i] + right[i];
}
}
for (int iter = 0; iter < maxshifts; iter++)
{
int lastleftadd = -1;
for (int i = 0; i < ar.Length; i++)
{
if (left[i] != 0 && ar[i] != 0)
{
ar[i]--;
ar[i - 1]++;
left[i]--;
}
else if (right[i] != 0 && ar[i] != 0
&& (ar[i] != 1 || lastleftadd != i))
{
ar[i]--;
ar[i + 1]++;
lastleftadd = i + 1;
right[i]--;
}
}
}
return maxshifts;
}

Resources