Number of K-Spikes in Stock Price Array
Last Updated :
23 Dec, 2023
Given the changes to stock price over a period of time as an array of distinct integers, count the number of spikes in the stock price which are counted as K-Spikes.
A K-Spike is an element that satisfies both the following conditions:
- There are at least K elements from indices (0, i-1) that are less than the price[i].
- There are at least K elements from indices (i+1, n-1) that are less than the price[i].
Examples:
Input: price = [1, 2, 8, 5, 3, 4], K = 2
Output: 2
Explanation: There are 2 K-Spikes:
• 8 at index 2 has (1, 2) to the left and (5, 3, 4) to the right that are less than 8.
• 5 at index 3 has (1, 2) to the left and (3, 4) to the right that are less than 5.
Input: price = [7, 2, 3, 9, 7, 4], K = 3
Output: 0
Explanation: There is no K-spike possible for any i. For element 9 there are at least 3 elements smaller than 9 on the left side but there are only 2 elements that are smaller than 9 on the right side.
Naive approach: The basic way to solve the problem is as follows:
The idea is to check for every element of the price array whether it is a K-spike or not.
- To check we calculate the number of elements that are smaller than prices[i] in the range [0 …… i-1]
- Calculate the number of elements that are smaller than the price[i] in the range[i+1 …… N] by again traversing using loops
- After that if the given condition is satisfied then the price[i] is K-spike then we increment our answer.
Time complexity: O(N2)
Auxillary space: O(1)
Efficient approach: To solve the problem follow the below idea:
In the naive approach we have traversed the array again for finding count of smaller elements till i-1 or from i+1, but how about precalculating the number of elements that are smaller than price[i] in range[0…… i-1] and also in range[i+1…..N) and storing them in an prefix and suffix array respectively.
Follow the steps to solve the problem:
- We construct two array’s prefix and suffix, prefix[i] denotes number of elements that are smaller than price[i] in [0……i-1] and suffix[i] denotes the number of elements that are smaller than price[i] in [i+1 …… N).
- To construct prefix array we maintain a ordered set(Policy based data structure) in which elements till index i-1 already present in set so we can find the position of price[i] in ordered set by using order_of_key function which gives number of items strictly smaller than price[i] then we just put this value at prefix[i] and at last we push price[i] in set.
- To construct suffix array we traverse the price array backwards and do the similar thing that we have done for prefix array.
- Now we have prefix and suffix array in our hand then we traverse the price aray and check if both prefix[i] and suffix[i] are at least K then we increment our answer.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
template < typename T>
using pbds = tree<T, null_type, less<T>, rb_tree_tag,
tree_order_statistics_node_update>;
int CalculateNumberOfKSpikes(vector< int >& price, int k)
{
int n = price.size();
pbds< int > st1, st2;
int countOfKspikes = 0;
vector< int > prefix(n + 1, 0), suffix(n + 1, 0);
for ( int i = 0; i < n; i++) {
prefix[i] = st1.order_of_key(price[i]);
st1.insert(price[i]);
}
for ( int i = n - 1; i >= 0; i--) {
suffix[i] = st2.order_of_key(price[i]);
st2.insert(price[i]);
}
for ( int i = 0; i < n; i++) {
if (prefix[i] >= k && suffix[i] >= k) {
countOfKspikes++;
}
}
return countOfKspikes;
}
int main()
{
vector< int > price = { 1, 2, 8, 5, 3, 4 };
int k = 2;
int countOfKspikes = CalculateNumberOfKSpikes(price, k);
cout << countOfKspikes;
return 0;
}
|
Java
import java.util.TreeSet;
public class Main {
static int calculateNumberOfKSpikes( int [] price, int k) {
int n = price.length;
TreeSet<Integer> st1 = new TreeSet<>();
TreeSet<Integer> st2 = new TreeSet<>();
int countOfKSpikes = 0 ;
int [] prefix = new int [n + 1 ];
int [] suffix = new int [n + 1 ];
for ( int i = 0 ; i < n; i++) {
prefix[i] = st1.headSet(price[i]).size();
st1.add(price[i]);
}
for ( int i = n - 1 ; i >= 0 ; i--) {
suffix[i] = st2.headSet(price[i]).size();
st2.add(price[i]);
}
for ( int i = 0 ; i < n; i++) {
if (prefix[i] >= k && suffix[i] >= k) {
countOfKSpikes++;
}
}
return countOfKSpikes;
}
public static void main(String[] args) {
int [] price = { 1 , 2 , 8 , 5 , 3 , 4 };
int k = 2 ;
int countOfKSpikes = calculateNumberOfKSpikes(price, k);
System.out.println(countOfKSpikes);
}
}
|
Python3
def calculate_number_of_k_spikes(price, k):
n = len (price)
st1 = set ()
st2 = set ()
count_of_k_spikes = 0
prefix = [ 0 ] * (n + 1 )
suffix = [ 0 ] * (n + 1 )
for i in range (n):
prefix[i] = len ([x for x in st1 if x < price[i]])
st1.add(price[i])
for i in range (n - 1 , - 1 , - 1 ):
suffix[i] = len ([x for x in st2 if x < price[i]])
st2.add(price[i])
for i in range (n):
if prefix[i] > = k and suffix[i] > = k:
count_of_k_spikes + = 1
return count_of_k_spikes
if __name__ = = "__main__" :
price = [ 1 , 2 , 8 , 5 , 3 , 4 ]
k = 2
count_of_k_spikes = calculate_number_of_k_spikes(price, k)
print (count_of_k_spikes)
|
C#
using System;
using System.Collections.Generic;
public class MainClass
{
static int CalculateNumberOfKSpikes( int [] price, int k)
{
int n = price.Length;
SortedSet< int > st1 = new SortedSet< int >();
SortedSet< int > st2 = new SortedSet< int >();
int countOfKSpikes = 0;
int [] prefix = new int [n + 1];
int [] suffix = new int [n + 1];
for ( int i = 0; i < n; i++)
{
prefix[i] = st1.GetViewBetween( int .MinValue, price[i]).Count;
st1.Add(price[i]);
}
for ( int i = n - 1; i >= 0; i--)
{
suffix[i] = st2.GetViewBetween( int .MinValue, price[i]).Count;
st2.Add(price[i]);
}
for ( int i = 0; i < n; i++)
{
if (prefix[i] >= k && suffix[i] >= k)
{
countOfKSpikes++;
}
}
return countOfKSpikes;
}
public static void Main( string [] args)
{
int [] price = { 1, 2, 8, 5, 3, 4 };
int k = 2;
int countOfKSpikes = CalculateNumberOfKSpikes(price, k);
Console.WriteLine(countOfKSpikes);
}
}
|
Javascript
function calculateNumberOfKSpikes(price, k) {
const n = price.length;
const st1 = new Set();
const st2 = new Set();
let countOfKSpikes = 0;
const prefix = new Array(n + 1).fill(0);
const suffix = new Array(n + 1).fill(0);
for (let i = 0; i < n; i++) {
prefix[i] = [...st1].filter(x => x < price[i]).length;
st1.add(price[i]);
}
st1.clear();
for (let i = n - 1; i >= 0; i--) {
suffix[i] = [...st2].filter(x => x < price[i]).length;
st2.add(price[i]);
}
for (let i = 0; i < n; i++) {
if (prefix[i] >= k && suffix[i] >= k) {
countOfKSpikes++;
}
}
return countOfKSpikes;
}
const price = [1, 2, 8, 5, 3, 4];
const k = 2;
const countOfKSpikes = calculateNumberOfKSpikes(price, k);
console.log(countOfKSpikes);
|
Time Complexity: O(N*logN)
Auxillary space: O(N), where N is the size of the array.
Share your thoughts in the comments
Please Login to comment...