Sparse Table or Stack?

Jimmy (xiaoke) Shen
3 min readDec 5, 2020

--

Last week’s contest, I met a pretty nice question which can be solved elegantly by using stack. However, before achieving that elegant solution, we can also use sparse table or segment tree to solve that problem

Problem

1673. Find the Most Competitive Subsequence

Solutions

Sparse Table O(n log n) 1852 ms

class Solution {
public:
void Build_SparseTable (vector<int>& vec, vector<vector<int>>& sparse_table) {
int rows = vec.size();
int cols = sparse_table[0].size();
for (int r=0; r<rows; r++)
sparse_table[r][0] = vec[r];
for (int c=1; c <= cols; c++) {
int range = (1 << c);
/* For c Range c-1 Previous Range
1 2^1 = 2 0 2^0 = 1
2 2^2 = 4 1 2^1 = 2
3 2^3 = 8 2 2^2 = 4
...
*/
for (int r=0; r + range <= rows; r++) {
// Values in the current column are derived from the
// values in the previous column.
sparse_table[r][c] = min (sparse_table[r][c-1],
sparse_table[r+(1<<(c-1))][c-1]);
}
}
}
int RMQ (int left, int right, vector<vector<int>>& sparse_table) {// Find the biggest block of size 2^p that fits in the range "left" till "right".int power_of_2 = (int) log2( right + 1 - left );
int x = right + 1 - ( 1 << power_of_2 );
//cout << "Left : " << left << " Right : " << right << endl;
//cout << "Part 1: (" << left << ".." << left + ( 1 << power_of_2 ) - 1 << ")" << " Part 2: (" << right + 1 - ( 1 << power_of_2 ) << ".." << right << ")" << endl;
if ( sparse_table[left][power_of_2] <= sparse_table[right + 1 - ( 1 << power_of_2 )][power_of_2] )
return sparse_table[left][power_of_2];
else
return sparse_table[right + 1 - ( 1 << power_of_2)][power_of_2];
}
vector<int> mostCompetitive(vector<int>& nums, int k) {
//int sz = ceil (log2 (vec.size()) ) + 1;
int sz = ceil (log2 (nums.size()) ) + 1;
unordered_map<int, vector<int>> m;
for (int i =0; i < nums.size(); i++) {
m[nums[i]].push_back(i);
}
// Create a sparse table of size [number_count][ceil ( log2 (number_count)) + 1]
vector<vector<int>> sparse_table (nums.size(), vector<int>(sz));


Build_SparseTable(nums, sparse_table);
vector<int> ret;
int l = 0, r = nums.size() - k;
for (int i = 0; i < k; ++i) {
r = nums.size() - k + i;
int this_ret = RMQ(l, r,sparse_table );
ret.push_back(this_ret);
l = *(lower_bound(m[this_ret].begin(), m[this_ret].end(), l)) + 1;
//cout<<"l"<<l<<endl;
if (nums.size() - l == k - i -1) {
for (int j = l; j < nums.size();++j){
ret.push_back(nums[j]);
}
return ret;
}

}
return ret;

}
};

Stack (O(n)) [1] 400 ms

class Solution {
public:
vector<int> mostCompetitive(vector<int>& nums, int k) {
vector<int> stack;
const int n = nums.size();
for (int i = 0; i < n; ++i) {
while (!stack.empty() && stack.back() > nums[i] &&
stack.size() - 1 + n - i >=k ){
stack.pop_back();
}
if (stack.size() < k) {
stack.push_back(nums[i]);
}
}
return stack;

}
};

Hard to understand at the beginning? Understand from an example.
Input: nums = [2,4,3,3,5,4,9,6], k = 4
Output: [2,3,3,4]

Output the whole process

nums0: 2
2
nums1: 4
2 4
nums2: 3
2 3
nums3: 3
2 3 3
nums4: 5
2 3 3 5
nums5: 4
2 3 3 4
nums6: 9
2 3 3 4
nums7: 6
2 3 3 4

Happy weekend. Happy coding and software engineering.

Similar problems [1]

Reference

[1] https://leetcode.com/problems/find-the-most-competitive-subsequence/discuss/952786/JavaC++Python-One-Pass-Stack-Solution

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

No responses yet

Write a response