I have created YouTube playlists by difficulties.
- Easy link
- Medium link
- Hard link
October 9, 2022
Problem:
Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.
Examples:
[2,3,4]
, the median is 3
[2,3]
, the median is (2 + 3) / 2 = 2.5
Design a data structure that supports the following two operations:
For example:
1 2 3 4 5 |
addNum(1) addNum(2) findMedian() = 1.5 addNum(3) findMedian() = 2 |
Idea:
Time Complexity:
add(num): O(logn)
findMedian(): O(logn)
Solution1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
// Author: Huahua // Running Time: 152 ms class MedianFinder { public: /** initialize your data structure here. */ MedianFinder() {} // l_.size() >= r_.size() void addNum(int num) { if (l_.empty() || num <= l_.top()) { l_.push(num); } else { r_.push(num); } // Step 2: Balence left/right if (l_.size() < r_.size()) { l_.push(r_.top()); r_.pop(); } else if (l_.size() - r_.size() == 2) { r_.push(l_.top()); l_.pop(); } } double findMedian() { if (l_.size() > r_.size()) { return static_cast<double>(l_.top()); } else { return (static_cast<double>(l_.top()) + r_.top()) / 2; } } private: priority_queue<int, vector<int>, less<int>> l_; // max-heap priority_queue<int, vector<int>, greater<int>> r_; // min-heap }; |
Solution 2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
// Author: Huahua // Running time: 172 ms class MedianFinder { public: /** initialize your data structure here. */ MedianFinder(): l_(m_.cend()), r_(m_.cend()) {} // O(logn) void addNum(int num) { if (m_.empty()) { l_ = r_ = m_.insert(num); return; } m_.insert(num); const size_t n = m_.size(); if (n & 1) { // odd number if (num >= *r_) { l_ = r_; } else { // num < *r_, l_ could be invalidated l_ = --r_; } } else { if (num >= *r_) ++r_; else --l_; } } // O(1) double findMedian() { return (static_cast<double>(*l_) + *r_) / 2; } private: multiset<int> m_; multiset<int>::const_iterator l_; // current left median multiset<int>::const_iterator r_; // current right median }; |
Related Problems
Problem:
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7
might become 4 5 6 7 0 1 2
).
Find the minimum element.
You may assume no duplicate exists in the array.
Idea:
Divide and conquer.
Evenly Split the array into two sub-arrays, and find the minimums of them, return the smaller one.
findMin(a[0..n]) = min(findMin(a[0..n/2], a[n/2..n])
Key property:
One of the sub-array will be a sorted array, it takes O(1) to find the minimal element, just the first element.
Time complexity:
T(n) = O(1) + T(n/2) = O(logn)
Solution:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// Author: Huahua class Solution { public: int findMin(vector<int> &num) { return findMin(num, 0, num.size()-1); } private: int findMin(const vector<int>& num, int l, int r) { // Only 1 or 2 elements if (l+1 >= r) return min(num[l], num[r]); // Sorted if (num[l] < num[r]) return num[l]; int mid = l + (r-l)/2; return min(findMin(num, l, mid-1), findMin(num, mid, r)); } }; |
Given a 2D board and a word, find if the word exists in the grid.
The word can be constructed from letters of sequentially adjacent cell, where “adjacent” cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.
For example,
Given board =
1 2 3 4 5 |
[ ['A','B','C','E'], ['S','F','C','S'], ['A','D','E','E'] ] |
word = "ABCCED"
, -> returns true
,
word = "SEE"
, -> returns true
,
word = "ABCB"
, -> returns false
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
class Solution { public: bool exist(vector<vector<char>> &board, string word) { if(board.size()==0) return false; h = board.size(); w = board[0].size(); for(int i=0;i<w;i++) for(int j=0;j<h;j++) if(search(board, word, 0, i, j)) return true; return false; } bool search(vector<vector<char>> &board, const string& word, int d, int x, int y) { if(x<0 || x==w || y<0 || y==h || word[d] != board[y][x]) return false; // Found the last char of the word if(d==word.length()-1) return true; char cur = board[y][x]; board[y][x] = 0; bool found = search(board, word, d+1, x+1, y) || search(board, word, d+1, x-1, y) || search(board, word, d+1, x, y+1) || search(board, word, d+1, x, y-1); board[y][x] = cur; return found; } private: int w; int h; }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# Author: Huahua, running time: 216 ms class Solution: def exist(self, board: List[List[str]], word: str) -> bool: if not board: return False h, w = len(board), len(board[0]) def search(d: int, x: int, y: int) -> bool: if x < 0 or x == w or y < 0 or y == h or word[d] != board[y][x]: return False if d == len(word) - 1: return True cur = board[y][x] board[y][x] = '' found = search(d + 1, x + 1, y) or search(d + 1, x - 1, y) or search(d + 1, x, y + 1) or search(d + 1, x, y - 1) board[y][x] = cur return found return any(search(0, j, i) for i in range(h) for j in range(w)) |