Maximum of all subarrays of size k - c++

PROBLEM: Given an array arr[] of size N and an integer K. Find the maximum for each and every contiguous subarray of size K.
Why doesn't the following test case pass for the code below:-
Input: 5 4 1 2 3 4 5 Its Correct output is:
4 5
And my Code's output is: 4 5 5
int find_max(queue<int> q){
int max = 0;
while (!q.empty())
{
if (q.front() > max)
max = q.front();
q.pop();
}
return max;
}
vector<int> max_of_subarrays(int *arr, int n, int k){
// your code here
vector<int> res;
queue<int> q;
vector<int> temp;
int i = 0, j = 0;
//for cases where n = k
if(k == n){
sort(arr, arr+n);
temp.push_back(arr[n-1]);
return temp;
}
while(j < n)
{
q.push(arr[j]);
if ((j - i + 1) < k)
{
j++;
}
else if((j - i + 1) == k)
{
int x = find_max(q);
res.push_back(x);
//removing first entered element from queue
q.pop();
//pushing the next element to the queue
q.push(arr[i]);
i++;
j++;
}
}
//for last window
int x = find_max(q);
res.push_back(x);
return res;
}
Can someone tell what's going wrong here?

Yes, we can help.
The line q.push(arr[i]); is wrong. Index i will not be the last element. So, rather index j+1 should be used. But this will be pushed anyway in the next loop run.
So, you do not need this line at all. Delete it!
And in your while loop, you find already all results. So, you can simply delete the last 2 lines
int x = find_max(q);
res.push_back(x);
Then your function will work.
But for real C++ it is too complicated.
You could also use the following approach with a `````std::deque````:
auto maxOfContiguousSubArray(std::vector<int>& data, size_t subArraySize) {
// Here we will store the result
std::vector<int> result{};
// And this will hold our subarray. We use a deque, because we will have then have required iterators
std::deque<int> subArray{};
// Special case: Number of elements is less or equal the subarray size
if (data.size() <= subArraySize) {
// Get the one max element
result.push_back(*std::max_element(data.begin(), data.end()));
}
// Go over all numbers in data
else for (size_t index{}; index < data.size(); index++) {
// Store value in sub array
subArray.push_back(data[index]);
// If there are enough values in subarray, then
if (index >= subArraySize-1 ) {
// Get the max value
result.push_back(*std::max_element(subArray.begin(), subArray.end()));
// Remove the first value
subArray.pop_front();
}
}
return result;
}
int main() {
size_t n{}, k{};
// Read number of elements and size of subarray
if (std::cin >> n >> k) {
// Here we will store our numbers
std::vector<int> data{};
// copy n numbers from std::cin into data
std::copy_n(std::istream_iterator<int>(std::cin), n, std::back_inserter(data));
// Calculate the max values
auto max = maxOfContiguousSubArray2(data, k);
// Show the user output
std::copy(max.begin(), max.end(), std::ostream_iterator<int>(std::cout, " "));
}
return 0;
}
But basically, you do not need a subarray at all. You can simply build a sliding door with iterators or with indices.
Then the function would look like that:
auto maxOfContiguousSubArray2(std::vector<int>& data, size_t subArraySize) {
// Here we will store the result
std::vector<int> result{};
// Special case: Number of elements is less or equal the subarray size
subArraySize = std::min(data.size(), subArraySize);
// Find the max element of the window
for (auto first{ data.begin() }, last{ data.begin() + subArraySize-1 }; last != data.end(); ++first, ++last)
result.push_back(*std::max_element(first, last));
return result;
}

Problem - Given an array arr[] of size N and an integer K. Find the maximum for each and every contiguous subarray of size K.
This is how "Maximum of all subarrays of size k" problem is implemented in Java
class Solution
{
static ArrayList <Integer> max_of_subarrays(int arr[], int n, int k)
{
int i = 0,j = 0;
ArrayList <Integer> ans = new ArrayList <Integer>();
Deque<Integer> q = new LinkedList<Integer>();
while(j<n){
while(q.isEmpty() == false && q.peekLast() < arr[j])
q.removeLast();
q.addLast(arr[j]);
if(j-i+1 < k)
j++;
else if(j-i+1 == k){
ans.add(q.peekFirst());
if(arr[i] == q.peekFirst())
q.removeFirst();
i++;
j++;
}
}
return ans;
}
}

Related

Finding the smallest positive number

Question: Smallest Positive missing number
What is wrong with this code?
class Solution
{
public:
//Function to find the smallest positive number missing from the array.
int missingNumber(int arr[], int n)
{
// Your code here
sort(arr,arr+n);
int index=1;
int a;
for(int i=0;i<n;i++){
if(arr[i]>0){
if(arr[i]!=index){
a=index;
break;
}
else{
index++;
}
}
}
return index;
}
};
In every iteration your i is increasing, so this condition which you have written in your for loop:
arr[i]!=index
Here, let's say if the input array has duplicate elements, then for 2 consecutive values of i you will get the same value in arr[i]. In the first comparison, this condition will hold false, so you go to the else part and increment the index value. In the next iteration, your condition arr[i]!=index is always going to be true, as arr[i] is still the same but the index is increased. Thus your program will break from the for loop and the index value is getting returned. That is where it's failing.
So, it will always fail whenever you have duplicate positive elements in your input array. Except for the case when the largest item in the array is the only duplicate in input.
Here's one hint:
for(int i=0;i<n;i++){
if(arr[i]>0){
if(arr[i]!=index){
a=index;
break;
}
else{
index++;
}
}
}
imagine your sorted array is [-10, -5, 0, 1, 2, 3, 4, 5]
When i==3. arr[3] is equal 1, which is the first number you want to evaluate against index. But index will be equal to 3, not 1 as you might have intended.
And as others have pointed out - duplicate numbers in the array are not handled either.
Second hint:
What if I told you... that there was a way to solve this problem without having to sort the input array at all? What if you had an allocated an array of bools of length N to work with....
You should only increase index if arr[i] == index or else you'll get the wrong result for arrays with duplicates, like {1,2,3,4,5,5,6,7}.
int missingNumber(int arr[], int n) {
std::sort(arr,arr + n);
int index=1;
int a;
for(int i=0; i < n; i++) {
if(arr[i] > 0) {
if(arr[i] == index) { // equal, step
++index;
} else if(arr[i] > index) { // greater, we found the missing one
a=index;
break;
} // else, arr[i] == index - 1, don't step
}
}
return index;
}
You are missing a great opportunity to use the sorted array though. Since you're only interested in positive numbers, you can use std::upper_bound to find the first positive number. This search is done very efficiently and it also means that you don't have to check if(arr[i] > 0) in every iteration of your loop.
Example:
int missingNumber(int arr[], int n) {
int* end = arr + n;
std::sort(arr, end);
int* it = std::upper_bound(arr, end, 0); // find the first number greater than 0
int expected = 1;
while(it != end && *it <= expected) {
if(*it == expected) ++expected;
++it;
}
return expected;
}
Alternatively, std::partition the array to put the positve numbers first in the array even before you sort it. That means that you'll not waste time sorting non-positive numbers.
int missingNumber(int arr[], int n) {
int* end = arr + n;
end = std::partition(arr, end, [](int x){ return x > 0; });
std::sort(arr, end);
int expected = 1;
for(int* it = arr; it != end && *it <= expected; ++it) {
if(*it == expected) ++expected;
}
return expected;
}
You can try using a counting array and then walk the array until you come to an empty space.
int main() {
int N;
cin >> N;
int num; // set to zero b/c zero is out lowest possible number
vector<int> numbers;
while (cin >> num) {
numbers.push_back(num);
}
//create a counting array to add a 1 to all the positions that exist
int * cA = new int[10000] {0};
for (int i = 0; i < N; i++) {
if (numbers[i] >= 0) {
cA[numbers[i]]++;
}
}
for (int i = 1; i < 10000; i++) {
if (cA[i] == 0) {
num = i;
break;
}
}
cout << num;
delete []cA;
return 0;
}
How Code Works : first get element count and add all items into Vector by Loop,with second loop going to 1000 i check from 1 to 1000 if any of 1,2,3,4,... is not in the vector i print missing,i do this with bool variable res,if any of loop counter starting from 1 to 1000 is in the vector res variable is set to True otherwise False.be careful in each run of For Loop from 1 to 1000 you should set res=False
#include <iostream>
#include <vector>
using namespace std;
//Programmer : Salar Ashgi
int main()
{
vector<int> v;
int k=0;
cout<<"Enter array count ?\n";
cin>>k;
int n;
for(int i=0;i<k;i++)
{
cout<<"Enter num "<<i+1<<" : ";
cin>>n;
v.push_back(n);
}
bool res=false;
for(int i=1;i<=1000;i++)
{
res=false;
for(int j=0;j<k;j++)
{
if(v[j]==i)
{
res=true;
break;
}
}
if(!res)
{
cout<<i<<" is missing !";
break;
}
}
}

Repeating elements in vector

I am a C++ student. And I need to solve this problem: "Write a program that receives a number and an array of the size of the given number. The program must find all the duplicates of the given numbers, push-back them to a vector of repeating elements, and print the vector". The requirements are I'm only allowed to use the vector library and every repeating element of the array must be pushed to the vector only once, e.g. my array is "1, 2, 1, 2, 3, 4...", the vector must be "1 ,2".
Here's what I've done so far. My code works, but I'm unable to make it add the same duplicate to the vector of repeating elements only once.
#include <iostream>
#include <vector>
int main() {
int n;
std::cin >> n;
int* arr = new int[n];
std::vector<int> repeatedElements;
for(int i = 0; i < n; ++i) {
std::cin >> arr[i];
}
for(int i = 0; i < n; ++i) {
bool foundInRepeated = false;
for(int j = 0; j < repeatedElements.size(); ++j) {
if(arr[i] == repeatedElements[j]) {
foundInRepeated = true;
break;
}
}
if(foundInRepeated) {
continue;
} else {
for(int i = 0; i < n; ++i) {
int count = 1;
for(int j = i + 1; j < n; ++j) {
if(arr[i] == arr[j]) {
++count;
}
}
if(count > 1) {
repeatedElements.push_back(arr[i]);
}
}
}
}
for(int i = 0; i < repeatedElements.size(); ++i) {
std::cout << repeatedElements[i] << " ";
}
std::cout << std::endl;
}
Consider what you're doing here:
if(foundInRepeated) {
continue;
} else {
for(int i = 0; i < n; ++i) { // why?
If the element at some index i (from the outer loop) is not found in repeatedElements, you're again iterating through the entire array, and adding elements that are repeated. But you already have an i that you're interested in, and hasn't been added to the repeatedElements. You only need to iterate through j in the else branch.
Removing the line marked why? (and the closing brace), will solve the problem. Here's a demo.
It's always good to follow a plan. Divide the bigger problem into a sequence of smaller problems is a good start. While this often does not yield an optimal solution, at least it yields a solution, which is more or less straightforward. And which subsequently can be optimized, if need be.
How to find out, if a number in the sequence has duplicates?
We could brute force this:
is_duplicate i = arr[i+1..arr.size() - 1] contains arr[i]
and then write ourselves a helper function like
bool range_contains(std::vector<int>::const_iterator first,
std::vector<int>::const_iterator last, int value) {
// ...
}
and use it in a simple
for (auto iter = arr.cbegin(); iter != arr.cend(); ++iter) {
if (range_contains(iter+1, arr.cend(), *iter) && !duplicates.contains(*iter)) {
duplicates.push_back(*iter);
}
}
But this would be - if I am not mistaken - some O(N^2) solution.
As we know, sorting is O(N log(N)) and if we sort our array first, we will
have all duplicates right next to each other. Then, we can iterate over the sorted array once (O(N)) and we are still cheaper than O(N^2). (O(N log(N)) + O(N) is still O(N log(N))).
1 2 1 2 3 4 => sort => 1 1 2 2 3 4
Eventually, while using what we have at our disposal, this could yield to a program like this:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
using IntVec = std::vector<int>;
int main(int argc, const char *argv[]) {
IntVec arr; // aka: input array
IntVec duplicates;
size_t n = 0;
std::cin >> n;
// Read n integers from std::cin
std::generate_n(std::back_inserter(arr), n,
[](){
return *(std::istream_iterator<int>(std::cin));
});
// sort the array (in ascending order).
std::sort(arr.begin(), arr.end()); // O(N*logN)
auto current = arr.cbegin();
while(current != arr.cend()) {
// std::adjacent_find() finds the next location in arr, where 2 neighbors have the same value.
current = std::adjacent_find(current,arr.cend());
if( current != arr.cend()) {
duplicates.push_back(*current);
// skip all duplicates here
for( ; current != (arr.cend() - 1) && (*current == *(current+1)); current++) {
}
}
}
// print the duplicates to std::cout
std::copy(duplicates.cbegin(), duplicates.cend(),
std::ostream_iterator<int>(std::cout, " "));
return 0;
}

Minimum Swaps 2 - minimum number of swaps required to sort a vector in ascending order

I'm doing a fairly easy HackerRank test which asks the user to write a function which returns the minimum number of swaps needed to sort an unordered vector in ascending order, e.g.
Start: 1, 2, 5, 4, 3
End: 1, 2, 3, 4, 5
Minimum number of swaps: 1
I've written a function which works on 13/14 test cases, but is too slow for the final case.
#include<iostream>
#include<vector>
using namespace std;
int mimumumSwaps(vector<int> arr) {
int p = 0; // Represents the (index + 1) of arr, e.g. 1, 2, ..., arr.size() + 1
int swaps = 0;
for (vector<int>::iterator i = arr.begin(); i != arr.end(); ++i) {
p++;
if (*i == p) // Element is in the correct place
continue;
else{ // Iterate through the rest of arr until the correct element is found
for (vector<int>::iterator j = arr.begin() + p - 1; j != arr.end(); ++j) {
if (*j == p) {
// Swap the elements
double temp = *j;
*j = *i;
*i = temp;
swaps++;
break;
}
}
}
}
return swaps;
}
int main()
{
vector<int> arr = { 1, 2, 5, 4, 3 };
cout << mimumumSwaps(arr);
}
How would I speed this up further?
Are there any functions I could import which could speed up processes for me?
Is there a way to do this without actually swapping any elements and simply working out the min. swaps which I imagine would speed up the process time?
All permutations can be broken down into cyclic subsets. Find said subsets.
Rotating a subset of K elements by 1 takes K-1 swaps.
Walk array until you find an element out of place. Walk that cycle until it completes. Advance, skipping elements that you've put into a cycle already. Sum (size-1) for each cycle.
To skip, maintain an ordered or unordered set of unexamined items, and fast remove as you examine them.
I think that gives optimal swap count in O(n lg n) or so.
#include <bits/stdc++.h>
#include <vector>
#include <algorithm>
using namespace std;
int minimumSwaps(vector<int> arr)
{
int i,c,j,k,l;
j=c=0;
l=k=arr.size();
while (j<k)
{
i=0;
while (i<l)
{
if (arr[i]!=i+1)
{
swap(arr[i],arr[arr[i]-1]);
c++;
}
i++;
}
k=k/2;
j++;
}
return c;
}
int main()
{
int n,q;
cin >> n;
vector<int> arr;
for (int i = 0; i < n; i++)
{
cin>>q;
arr.push_back(q);
}
int res = minimumSwaps(arr);
cout << res << "\n";
return 0;
}

How to find inversion pairs in an array and their index positions?

I find difficult to find the inversion pairs in the array. I got the number of inversion pairs in the array but the logic seems so complex that I can't able to list pairs. I am new to C++, any help is appreciated.
Example:
Input: arr[] = {8, 4, 2, 1}
Output: 6
Expecting this output
Given array has six inversions (8,4) and index(0,1), (4,2) and index(1,2),
(8,2) and index(0,2), (8,1) and index(0,3), (4,1) and index(1,3), (2,1) and index(2,4)
// C++ program to count inversions using Binary Indexed Tree
#include<bits/stdc++.h>
using namespace std;
// Returns sum of arr[0..index]. This function assumes
// that the array is preprocessed and partial sums of
// array elements are stored in BITree[].
int getSum(int BITree[], int index)
{
int sum = 0; // Initialize result
// Traverse ancestors of BITree[index]
while (index > 0)
{
// Add current element of BITree to sum
sum += BITree[index];
// Move index to parent node in getSum View
index -= index & (-index);
}
return sum;
}
// Updates a node in Binary Index Tree (BITree) at given index
// in BITree. The given value 'val' is added to BITree[i] and
// all of its ancestors in tree.
void updateBIT(int BITree[], int n, int index, int val)
{
// Traverse all ancestors and add 'val'
while (index <= n)
{
// Add 'val' to current node of BI Tree
BITree[index] += val;
// Update index to that of parent in update View
index += index & (-index);
}
}
// Returns inversion count arr[0..n-1]
int getInvCount(int arr[], int n)
{
int invcount = 0; // Initialize result
// Find maximum element in arr[]
int maxElement = 0;
for (int i=0; i<n; i++)
if (maxElement < arr[i])
maxElement = arr[i];
// Create a BIT with size equal to maxElement+1 (Extra
// one is used so that elements can be directly be
// used as index)
int BIT[maxElement+1];
for (int i=1; i<=maxElement; i++)
BIT[i] = 0;
// Traverse all elements from right.
for (int i=n-1; i>=0; i--)
{
// Get count of elements smaller than arr[i]
invcount += getSum(BIT, arr[i]-1);
// Add current element to BIT
updateBIT(BIT, maxElement, arr[i], 1);
}
return invcount;
}
// Driver program
int main()
{
int arr[] = {8, 4, 2, 1};
int n = sizeof(arr)/sizeof(int);
cout << "Number of inversions are : " << getInvCount(arr,n);
return 0;
}
The program creates new array BITree[] that makes it more complex. How the position of the element is found.

Finding the second smallest sum of contiguous sub arrays

I am writing a function that takes in a pointer that points to an array that is dynamically allocated, in addition to the length of the array. I am trying to find the second smallest sum of it's contiguous sub arrays.
I have been writing code to calculate the second smallest value in an array, and also a piece of code that calculates the sum of all the contiguous sub arrays. I was hoping that I would be able to "merge" these two pieces together to get what my desired end result, but I am getting stuck. I would really appreciate any help.
Thank you.
#include <iostream>
using namespace std;
int secondSmallestSum(int *numbers,int length)
{
//Below shows the sum of all contiguous sub arrays.
for(i = 0; i<= length; ++i)
{
int sum = 0;
for(int j = i; j <= length; ++j)
{
sum+=*(numbers+j);
}
}
//Below calculates the second smallest element in an array
int smallest, secondsmallest;
if (*numbers < *(numbers+1))
{
smallest = *numbers;
secondsmallest = *(numbers+1) ;
}
else {
smallest = *(numbers+1) ;
secondsmallest = *(numbers) ;
}
for (i = 2; i < length; i++) {
if (*(numbers+i) < smallest)
{
secondsmallest = smallest;
smallest = *(numbers+i);
}
else if (*(numbers+i) < secondsmallest)
{
secondsmallest = *(numbers+i);
}
}
}
You can do something like this (of course you need to add range checking).
#include <iostream>
#include <vector>
#include <algorithm>
int main(int argc, char** argv) {
std::vector<int> v{3, 1, 4, 5, 6, 2};
std::nth_element(v.begin(), v.begin() + 1, v.end());
std::cout << "The second smallest element is " << v[1] << "\n";
}
Note: using nth_element will change the order of the elements in the vector.
Correct me if I understand you wrong,
by looking at "find the second smallest sum of it's contiguous sub arrays" and the code you posted, I'm assuming your logic is
calculate all sums of all possible contiguous sub arrays
find the second smallest value in the sums
Actually there is a well known algorithm, Kadane's algorithm, that serves a similar purpose (only Kadane's finds THE smallest, not second smallest). You may want to Google it to find more.
Back to your question, I believe the following code does what you want. The code is a variant of Kadane's algorithm.
#include <climits> // for INT_MAX
int findSecondMinOfContiguousSubarray(int arr[], int n)
{
// to store the minimum value that is ending
// up to the current index
int min_ending_here = INT_MAX;
int min = INT_MAX; // absolute min
int min_second = INT_MAX - 1; // second min <- this is what you want
// traverse the array elements
for (int i = 0; i<n/*it is <, not <=*/; i++)
{
// if min_ending_here > 0, then it could not possibly
// contribute to the minimum sum further
if (min_ending_here > 0)
min_ending_here = arr[i];
// else add the value arr[i] to min_ending_here
else
min_ending_here += arr[i];
// update min and min_second
if (min_second > min_ending_here) {
if (min > min_ending_here) {
min_second = min;
min = min_ending_here;
}
else {
min_second = min_ending_here;
}
}
}
return min_second;
}
BTW, I think your code (the piece under //Below shows the sum of all contiguous sub arrays.) can not find all contiguous sub arrays.
An example, arr={1, 2, 3}, your code only consider {1,2,3}, {2,3} and {3} as contiguous sub arrays, while in fact {1,2} should also be considered.
Brutal force o(n^2) complexity (in C++ style not C style):
template<typename Container, typename Func>
void forEachSubrange(Container &container, Func &&f)
{
for (auto subBegin = container.begin(); subBegin != container.end(); ++subBegin)
{
auto subEnd = subBegin;
do {
++subEnd;
f(subBegin, subEnd);
} while (subEnd != container.end());
}
}
int secondSmallestSubrangeSum(const std::vector<int> &a)
{
int firstSum = 0; // empty sub range has zero sum
int secondSum = 0;
forEachSubrange(a, [&firstSum, &secondSum](auto b, auto e) {
auto sum = std::accumulate(b, e, 0);
if (sum < firstSum) {
secondSum = firstSum;
firstSum = sum;
} else if (sum < secondSum) {
secondSum = sum;
}
});
return secondSum;
}
I'm sure it is possible to achieve o(n).
https://wandbox.org/permlink/9cplKBIpfZBPpZ27
or more talkative https://wandbox.org/permlink/X21TdH6xtbMLpV19