August LeetCoding Challenge
Day1
359.Logger Rate Limiter
Design a logger system that receive stream of messages along with its timestamps, each message should be printed if and only if it is not printed in the last 10 seconds.
Given a message and a timestamp (in seconds granularity), return true if the message should be printed in the given timestamp, otherwise returns false.
It is possible that several messages arrive roughly at the same time.
1.hashmap
#include <map>
#include <iostream>
#include <cassert>
using namespace std;
struct Logger {
map<string, int> map_keyword_time;
bool shouldPrintMessage(int ts, const string &s) {
if (map_keyword_time.find(s) != map_keyword_time.end()) {
if (ts - 10 < map_keyword_time[s]) {
return false;
}
}
map_keyword_time[s] = ts;
return true;
}
};
int main() {
Logger logger = Logger();
// logging string "foo" at timestamp 1
assert(logger.shouldPrintMessage(1, "foo") == true);
// logging string "bar" at timestamp 2
assert(logger.shouldPrintMessage(2,"bar")== true);// returns true;
// logging string "foo" at timestamp 3
assert(logger.shouldPrintMessage(3,"foo") == false); //returns false;
// logging string "bar" at timestamp 8
assert(logger.shouldPrintMessage(8,"bar") == false); //returns false;
// logging string "foo" at timestamp 10
assert(logger.shouldPrintMessage(10,"foo") == false); //returns false;
// logging string "foo" at timestamp 11
assert(logger.shouldPrintMessage(11,"foo") == true); //returns true;
}
string一直存在hashmap里面很耗内存->queue&set来优化
queue & set
#include <set>
#include <queue>
#include <iostream>
#include <cassert>
using namespace std;
struct Logger {
struct Log {
string msg {};
int ts;
Log (string msg, int ts) : msg(msg), ts(ts)
{}
};
set<string> msgSet;
queue<Log> qLogs;
bool shouldPrintMessage(int ts, const string &s) {
if (msgSet.find(s) != msgSet.end()) {
while (qLogs.size() && qLogs.front().ts +10 <= ts) {
Log log = qLogs.front();
msgSet.erase(log.msg);
qLogs.pop();
if (log.msg == s) {
log.ts = ts;
qLogs.push(log);
return true;
}
}
} else {
msgSet.insert(s);
qLogs.push(Log {s, ts});
return true;
}
return false;
}
};
520. Detect Capital
可精简掉switch
class Solution {
public:
bool detectCapitalUse(string word) {
int flag = 0; // all uppercase
if (word[0] > 'Z') flag = 1; // all lowercase
else if (word.length() > 1 && word[1] > 'Z') flag = 2; // first uppercase
switch(flag) {
case 0:
for (auto c : word) {
if (c > 'Z') return false;
}
break;
case 1:
for (auto c : word) {
if (c < 'a') return false;
}
break;
case 2:
for (int i=1; i<word.length(); i++) {
if (word[i] < 'a') return false;
}
}
return true;
}
};
705.Design HashSet
bitset
class MyHashSet {
bitset<1000001> data;
public:
/** Initialize your data structure here. */
MyHashSet()
{
}
void add(int key) {
data[key] = 1;
}
void remove(int key) {
data[key] = 0;
}
/** Returns true if this set contains the specified element */
bool contains(int key) {
return data[key];
}
};
不用bitset用array和fill也ok
array<bool, 1000001> data;
fill(data.begin(), data.end(), false);
or
bool data[1000001] = {false};
bucket
class MyHashSet {
static const int MAGIC_VALUE = 366661;
vector<vector<int>> hash;
public:
/** Initialize your data structure here. */
MyHashSet() : hash(MAGIC_VALUE-1)
{}
void add(int key) {
int idx = key % MAGIC_VALUE;
if (find(hash[idx].begin(), hash[idx].end(), idx) == hash[idx].end()) {
hash[idx].push_back(key);
}
}
void remove(int key) {
int idx = key % MAGIC_VALUE;
auto it = find(hash[idx].begin(), hash[idx].end(), idx);
if (it != hash[idx].end()) {
hash[idx].erase(it);
}
}
/** Returns true if this set contains the specified element */
bool contains(int key) {
int idx = key % MAGIC_VALUE;
return find(hash[idx].begin(), hash[idx].end(), idx) != hash[idx].end();
}
};
125.Valid Palindrome
isdigit
isalpha
tolower
class Solution {
public:
bool isPalindrome(string s) {
int size = s.length();
int fast = size-1;
int slow = 0;
while (fast > slow) {
while (fast >= 0 && !(isalpha(s[fast]) || isdigit(s[fast]))) fast --;
while (slow < size && !(isalpha(s[slow]) || isdigit(s[slow]))) slow ++;
if (fast >= 0 && slow < size) {
if (!(isalpha(s[fast]) ^ isdigit(s[slow]))) return false;
else if (tolower(s[fast]) != tolower(s[slow])) return false;
}
fast --;
slow ++;
}
return true;
}
};
342. Power of Four
class Solution {
public:
bool isPowerOfFour(int num) {
while (num / 4) {
if (num % 4) return false;
num /= 4;
}
return num == 1;
}
};
211.Add and Search Word - Data Structure Design
trie tree/ Prefix Tree
trie node
struct TrieNode {
map<char, TrieNode*> children;
bool isCompleted;
TrieNode() : isCompleted(false)
{}
};
class WordDictionary {
struct TrieNode {
map<char, TrieNode*> children;
bool isCompleted;
TrieNode() : isCompleted(false)
{}
};
TrieNode *header;
public:
/** Initialize your data structure here. */
WordDictionary() : header(new TrieNode())
{}
/** Adds a word into the data structure. */
void addWord(string word) {
auto lHeader = header;
for (auto c: word) {
if (lHeader->children.find(c) == lHeader->children.end()) {
lHeader->children[c] = new TrieNode();
}
lHeader = lHeader->children[c];
}
lHeader->isCompleted = true;
}
/** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
bool check(int idx, string &word, TrieNode *lHeader) {
char c = word[idx];
if (idx == word.length() - 1) {
if(word[idx] == '.') {
for (auto [key, val] : lHeader->children) {
if (val->isCompleted) return true;
}
return false;
} else {
return lHeader->children.find(word[idx]) != lHeader->children.end() ?
lHeader->children[word[idx]]->isCompleted : false;
}
}
if (c == '.') {
for (auto [key, val] : lHeader->children) {
if (check(idx+1, word, val)) return true;
}
} else {
if (lHeader->children.find(word[idx]) == lHeader->children.end()) return false;
if (check(idx+1, word, lHeader->children[word[idx]])) return true;
}
return false;
}
bool search(string word) {
return check(0, word, header);
}
};
442. Find All Duplicates in an Array
O(N) & no extra space
不停换位(其实就是在排序了),再遍历找坐标不符合的(出现了两次的)
class Solution {
public:
vector<int> findDuplicates(vector<int>& nums) {
for(int i=0; i<nums.size(); i++){
while(nums[i] != nums[nums[i]-1])
swap(nums[i], nums[nums[i]-1]);
}
vector<int>v {};
for(int i=0; i<nums.size(); i++){
if(nums[i] != i+1){
v.push_back(nums[i]);
}
}
return v;
}
};
原地取反,如果发现坐标对应的那个数已经为负数,就说明出现了两次
class Solution {
public:
int abs(int num) {
return num < 0? -num : num;
}
vector<int> findDuplicates(vector<int>& nums) {
vector<int> res {};
for (int i = 0; i < nums.size(); i++) {
if (nums[abs(nums[i]) - 1] < 0)
res.push_back(abs(nums[i]));
nums[abs(nums[i]) - 1] *= -1;
}
return res;
}
};
987. Vertical Order Traversal of a Binary
按层份bfs的思路(因为要保证同x情况下,大小按顺序排列,不然简单bfs就行),用set自动排序的思路也行,空间换时间
class Solution {
public:
vector<vector<int>> verticalTraversal(TreeNode* root) {
vector<vector<int>> res {};
if (!root) return res;
queue<pair<TreeNode*, int>> q {{{root, 0}}};
map<int, vector<int>> mapX_vals {};
while(q.size()) {
map<int, int> cntr {};
size_t size = q.size();
for (size_t i = 0; i<size; i++) {
auto [node, x] = q.front(); q.pop();
mapX_vals[x].push_back(node->val);
cntr[x] ++;
if (node->left) q.push({node->left, x-1});
if (node->right) q.push({node->right, x+1});
}
for (auto [x, cnt] : cntr)
sort(mapX_vals[x].end()-cnt, mapX_vals[x].end());
}
for (auto &&[x, vec] : mapX_vals) {
res.emplace_back(move(vec));
}
return res;
}
};
Day2
437. Path Sum III
bfs+dfs
class Solution {
public:
int pathSum(TreeNode* root, int sum) {
if (!root) return 0;
int cnt = 0;
queue<TreeNode*> q {{root}};
while (q.size()) {
auto node = q.front();
q.pop();
cnt += dfs(node, sum);
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
return cnt;
}
int dfs(TreeNode* root, int re) {
int cnt = 0;
if (!root) return cnt;
// t << re << ", " << root->val << endl;
if (root->val == re)
cnt+=1;
cnt += dfs(root->left, re-root->val);
cnt += dfs(root->right, re-root->val);
return cnt;
}
};
dfs+dfs
class Solution {
public:
int pathSum(TreeNode* root, int sum) {
if (!root) return 0;
int cnt = 0;
cnt += dfs(root, sum);
cnt += pathSum(root->left, sum);
cnt += pathSum(root->right, sum);
return cnt;
}
int dfs(TreeNode* root, int re) {
if (!root) return 0;
int cnt = 0;
if (root->val == re)
cnt+=1;
cnt += dfs(root->left, re-root->val);
cnt += dfs(root->right, re-root->val);
return cnt;
}
};
994. Rotting Oranges
bfs + 矩阵操作
class Solution {
public:
int dx[4] {0, 0, 1, -1};
int dy[4] {1, -1, 0, 0};
int orangesRotting(vector<vector<int>>& grid) {
if (grid.empty()) return 0;
// bfs + 矩阵操作
queue<pair<int, int>> q {};
int row = grid.size(), col = grid[0].size();
int tmr = 0, nFresh = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (grid[i][j] == 1) nFresh ++;
else if (grid[i][j] == 2) q.push({i,j});
}
}
while(q.size()) {
int size = q.size();
for (int i = 0; i < size; i++) {
auto [x, y] = q.front();
q.pop();
for (int z = 0; z < 4; z++) {
int new_i = x + dx[z], new_j = y + dy[z];
if (new_i >= 0 && new_i < row && new_j >= 0 && new_j < col && grid[new_i][new_j] == 1){
nFresh --;
grid[new_i][new_j] = 2;
q.push({new_i, new_j});
}
}
}
if (q.size()) tmr++;
}
if (nFresh) return -1;
return tmr;
}
};
171. Excel Sheet Column Number
class Solution {
public:
int titleToNumber(string s) {
int sum = 0; size_t ss = s.length();
for (size_t i = 0; i < ss; i++)
sum += (s[ss-i-1]-'A'+1) * pow(26, i);
return sum;
}
};
274. H-Index
sort
class Solution {
public:
int hIndex(vector<int>& citations) {
sort(citations.begin(), citations.end(), [] (int x, int y) {return x > y;});
for (int i=0; i<citations.size(); i++) {
if (citations[i] < i+1) return i;
}
return citations.size();
}
};
119. Pascal's Triangle II
class Solution {
public:
vector<int> getRow(int rowIndex) {
vector<int> res(rowIndex+1, 1);
for (int i=2; i<=rowIndex; i++) {
vector<int> tmp = res;
for (int j=1; j<i; j++) {
res[j]=tmp[j-1]+tmp[j];
}
}
return res;
}
};
!1286. Iterator for Combination
使用bitset做permutation (int当bitset, __builtin_popcount && 位运算找1)
class CombinationIterator {
public:
queue<string> strs {};
CombinationIterator(string str, int cl) {
int ss = str.length();
int maxBitset = (1 << ss) - 1;
for (int bs = maxBitset; bs > 0; bs--) {
if (__builtin_popcount(bs) != cl) continue;
int tmp_bs = bs, idx = 0;
string substr {};
while(tmp_bs) {
if (tmp_bs & 1) substr+=str[ss-1-idx];
tmp_bs >>= 1;
idx ++;
}
strs.push({substr.rbegin(), substr.rend()});
}
}
string next() {
if (strs.empty()) return nullptr;
auto res = strs.front();
strs.pop();
return res;
}
bool hasNext() {
return !strs.empty();
}
};
/**
* Your CombinationIterator object will be instantiated and called as such:
* CombinationIterator* obj = new CombinationIterator(characters, combinationLength);
* string param_1 = obj->next();
* bool param_2 = obj->hasNext();
*/
内存优化版
class CombinationIterator {
public:
string msg {};
int bs;
int lenMsg;
CombinationIterator(string str, int cl) :
msg(move(str)),
lenMsg(cl),
bs((1 << msg.length()) - 1) // str is moved ... so bs will be 0 if we use str
{}
string next() {
if (!hasNext()) return {};
int tmp_bs = bs, idx = 0;
string substr {};
while(tmp_bs) {
if (tmp_bs & 1) substr+=msg[msg.length()-1-idx];
tmp_bs >>= 1;
idx ++;
}
bs --;
return {substr.rbegin(), substr.rend()};
}
bool hasNext() {
while(bs && __builtin_popcount(bs) != lenMsg) bs--;
return bs;
}
};
409. Longest Palindrome
intuitive
class Solution {
public:
int longestPalindrome(string s) {
map<char, int> m {};
for (char c: s) m[c] ++;
int cnt = 0;
bool hasOven {false};
for (auto [key, val] : m) {
if (val%2) {
hasOven = true;
cnt += (val-1);
} else cnt += val;
}
return cnt + (int)hasOven;
}
};
270.Closest Binary Search Tree Value
dfs + 记录
k个值->dfs + heap
Day3
435. Non-overlapping Intervals
sort+greedy
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
if (intervals.empty()) return 0;
sort(intervals.begin(), intervals.end(), [](vector<int> &v, vector<int> &v2) {
return v[1] < v2[1];
});
int cnt=0, b=-0x7fffffff;
for (auto v:intervals) {
if (b>v[0]) cnt++;
else b=v[1];
}
return cnt;
}
};
53. Maximum Subarray
dp + push
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if (nums.empty()) return 0;
int ss = nums.size();
vector<int> memo(ss+1);
int maxi = -0x7fffffff;
for (int i=0; i<ss; i++) {
memo[i+1] = max(nums[i], memo[i]+nums[i]); // 若合大于0,保留
maxi = max(memo[i+1], maxi);
}
return maxi;
}
};
121. Best Time to Buy and Sell Stock
简化的双指针
class Solution {
public:
int maxProfit(vector<int>& prices) {
if (prices.size() < 2) return 0;
int res = 0, mini = prices[0];
for (int i=1; i<prices.size(); i++) {
res = max(res, prices[i]-mini);
mini = min(prices[i], mini);
}
return res;
}
};
122. Best Time to Buy and Sell Stock II
class Solution {
public:
int maxProfit(vector<int>& prices) {
if (prices.size()<2) return 0;
int res=0;
for (int i=1; i<prices.size(); i++) {
if (prices[i]>prices[i-1]) res+=prices[i]-prices[i-1];
}
return res;
}
};
123. Best Time to Buy and Sell Stock III
最多两次
1103. Distribute Candies to People
class Solution {
public:
vector<int> distributeCandies(int candies, int num_people) {
if (!num_people) return {};
vector<int> p (num_people);
int idx = 0, nCandy = 1;
while (candies) {
for (int i=0; i<num_people; i++) {
if (nCandy < candies) {
p[i] += nCandy;
candies-=nCandy++;
} else {
p[i] += candies;
candies = 0;
break;
}
}
}
return p;
}
};
967. Numbers With Same Consecutive Differences
824. Goat Latin
class Solution {
public:
string toGoatLatin(string S) {
if (S.length() < 1) return S;
set<char> cset {'a', 'e', 'o', 'i', 'u'};
stringstream ss(S);
string token {};
string ending = "a";
string res = "";
while (getline(ss, token, ' ')) {
char endc = token[token.size()-1];
if (cset.find(tolower(token[0])) == cset.end()) {
char c = token[0];
token = token.substr(1) + c;
}
res += token + "ma" + ending + " ";
ending += "a";
}
return {res.begin(), res.end()-1};
}
};
143. Reorder List
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
void reorderList(ListNode* head) {
if (!head) return;
stack<ListNode*> s {{head}};
auto tHead = head;
int size=1;
while(tHead->next) {
tHead = tHead->next;
s.push(tHead);
size++;
}
for (int i=0; i<size/2; i++) {
auto next = head->next;
auto backNode = s.top(); s.pop();
head->next = backNode;
backNode->next = next;
head = next;
}
head->next = nullptr;
}
};
905. Sort Array By Parity
双指针
class Solution {
public:
vector<int> sortArrayByParity(vector<int>& A) {
int ss = A.size(), idx = ss-1;
for (int i=0; i<ss; i++) {
while(idx>i && A[i] % 2) swap(A[i], A[idx--]);
}
return A;
}
};