Summary
It is a little busy this week. So the summary is a little late.
Solved problems list
- 1185. Day of the Week
- 1154. Day of the Year
- 1360. Number of Days Between Two Dates
- 1370. Increasing Decreasing String
- 1356. Sort Integers by The Number of 1 Bits
- 1372. Longest ZigZag Path in a Binary Tree
- 1362. Closest Divisors
- 220. Contains Duplicate III
- 211. Add and Search Word - Data structure design
- 209. Minimum Size Subarray Sum
- 208. Implement Trie (Prefix Tree)
- 207. Course Schedule
- 1365. How Many Numbers Are Smaller Than the Current Number
- 1367. Linked List in Binary Tree
- 1366. Rank Teams by Votes
Highlight
Code Section
The sequence of code is the same with the problem list.
// 1185. Day of the Week
// https://leetcode.com/problems/day-of-the-week/
class Solution {
public:
string dayOfTheWeek(int day, int month, int year) {
vector<vector<int>> cols{
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
function<bool(int)> is_leap_year = [](int y) {
if (y % 100 != 0) return y % 4 == 0;
else return y % 400 == 0;
};
int days = 0;
vector<int> y_d{365, 366};
for (int i = 1971; i < year; ++i) {
days += y_d[is_leap_year(i)];
}
auto& m = cols[is_leap_year(year)];
days += accumulate(begin(m), next(m.begin(), month-1), 0) + day;
days %= 7;
vector<string> weeks = {"Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday"};
return weeks[days == 0? 6 : days-1];
}
};
// 1154. Day of the Year
// https://leetcode.com/problems/day-of-the-year/
class Solution {
public:
int dayOfYear(string date) {
vector<int> time(3);
int size = date.size();
vector<vector<int>> cols{
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
time[0] = stoi(date.substr(0, 4));
time[1] = stoi(date.substr(5, 2));
time[2] = stoi(date.substr(8, 2));
function<bool(int)> is_leap_year = [](int y) {
if (y % 100 != 0) return y % 4 == 0;
else return y % 400 == 0;
};
vector<int>& col = cols[is_leap_year(time[0])];
return accumulate(begin(col), next(begin(col), time[1]-1), 0) + time[2];
}
};
// 1360. Number of Days Between Two Dates
// https://leetcode.com/problems/number-of-days-between-two-dates/
class Solution {
public:
int daysBetweenDates(string date1, string date2) {
vector<vector<int>> month_days = {
{31, 28, 31, 30,31,30,31,31,30,31,30,31},
{31, 29, 31, 30,31,30,31,31,30,31,30,31},
};
int leap_days[2] = {365, 366};
int y1, m1, d1;
int y2, m2, d2;
function<void(int&, int&, int&, string&)> parse = [](int&y ,int& m, int& d, string& s) {
y = stoi(s.substr(0, 4));
m = stoi(s.substr(5, 2));
d = stoi(s.substr(8, 2));
};
function<bool(int)> is_leap = [](int y) {
if (y % 100 == 0) return y % 400 == 0;
return y % 4 == 0;
};
parse(y1, m1, d1, date1);
parse(y2, m2, d2, date2);
int days = 0;
int s1 = y1, s2 = y2;
if (s1 > s2) swap(s1, s2);
for (int i = s1; i < s2; ++i) {
days += leap_days[is_leap(i)];
}
auto& m_d1 = month_days[is_leap(y1)];
int days1 = d1 + accumulate(begin(m_d1), next(m_d1.begin(), m1-1), 0);
auto& m_d2 = month_days[is_leap(y2)];
int days2 = d2 + accumulate(begin(m_d2), next(m_d2.begin(), m2-1), 0);
if (y1 < y2) {
return days + days2 - days1;
} else if (y1 > y2) {
return days + days1 - days2;
} else {
return abs(days1 - days2);
}
}
};
// 1370. Increasing Decreasing String
// https://leetcode.com/problems/increasing-decreasing-string/
class Solution {
public:
string sortString(string s) {
vector<int> x(26, 0);
for_each(begin(s), end(s), [&](char c) { ++x[c-'a'];});
string res;
int size = s.size();
while (res.size() < size) {
for (int i = 0; i < 26; ++i) {
if (x[i] != 0) {
res += i + 'a';
--x[i];
}
}
for (int i = 25; i >= 0; --i) {
if (x[i] != 0) {
res += i + 'a';
--x[i];
}
}
}
return res;
}
};
// 1356. Sort Integers by The Number of 1 Bits
// https://leetcode.com/problems/sort-integers-by-the-number-of-1-bits/
class Solution {
public:
vector<int> sortByBits(vector<int>& arr) {
unordered_map<int, int> cached;
function<int(int)> n_b = [&](int n) {
if (cached.find(n) != cached.end()) return cached[n];
int key = n;
int cnt = 0;
while (n != 0) { n &= (n-1); ++cnt;}
cached[key] = cnt;
return cnt;
};
function<bool(int, int)> cmp = [&](int l, int r) {
auto ll = n_b(l);
auto rr = n_b(r);
return ll == rr ? l < r : ll < rr;
};
sort(begin(arr), end(arr), cmp);
return arr;
}
};
// 1372. Longest ZigZag Path in a Binary Tree
// https://leetcode.com/problems/longest-zigzag-path-in-a-binary-tree/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int longestZigZag(TreeNode* root) {
if (!root || (!root->left && !root->right)) return 0;
int max_length = 0;
function<int(TreeNode*, bool, int)> traverse = [&](TreeNode* node, bool d, int n)
{
// d: true, right
// d: false, left
if (!node) return n;
n = n + 1;
int x, y;
if (d) {
x = node->right ? traverse(node->right, !d, n) : n;
y = node->left ? traverse(node->left, d, 0) : 0;
} else {
x = node->left ? traverse(node->left, !d, n) : n;
y = node->right ? traverse(node->right, d, 0) : 0;
}
return max(x, y);
};
return max(traverse(root->left, true, 0), traverse(root->right, false, 0));
}
};
// 1362. Closest Divisors
// https://leetcode.com/problems/closest-divisors/
class Solution {
public:
vector<int> closestDivisors(int num) {
int s = num + 2;
int k = sqrt(s);
for (; k >= 1; --k) {
auto x = (num+1) % k;
if (x == 0) return {k, (num+1)/k};
if (x == (k-1)) return {k, (num+2)/k};
}
return {0, 0};
}
vector<int> closestDivisorsSlow(int num) {
int a = num + 1;
int b = num + 2;
function<bool(int)> is_prime = [](int x) {
if (x == 1) return false;
if (x < 4) return true;
if (x % 2 == 0 || x % 3 == 0) return false;
int w = 2;
int k = 5;
while (k * k <= x) {
if (x % k == 0) return false;
k += w;
w = 6 - w;
}
return true;
};
function<pair<int,int>(int)> factor = [&](int n) {
if (is_prime(n)) return make_pair(1, n);
int r = (int)sqrt(n);
while (n % r != 0) {
++r;
}
int d = n / r;
if (d > r) swap(d, r);
return make_pair(d, r);
};
auto p1 = factor(a);
auto p2 = factor(b);
if (p1.second - p1.first < p2.second - p2.first) {
return {p1.first, p1.second};
} else {
return {p2.first, p2.second};
}
}
};
// 220. Contains Duplicate III
// https://leetcode.com/problems/contains-duplicate-iii/
class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
int size = nums.size();
if (k == 0 || size < 2) return false;
multiset<int> s;
s.insert(nums[0]);
// cout << "--------------" << endl;
for (int i = 1; i < size; ++i) {
auto l = s.lower_bound(nums[i]);
decltype(l) r = prev(l);
/*
if (l != s.end()) cout << "*l = " << *l << endl;
else cout << "*l is end()" << endl;
cout <<"*prev(l) = " << *prev(l) << endl;
*/
if (l != s.end() && (abs(*l - (long long)nums[i])) <= t) return true;
if (r != s.end() && (abs(*prev(l) - (long long)nums[i])) <= t) return true;
// cout << "X: " << nums[i]<< " "<< s.size() << endl;
if (s.size() == k) {
auto ite = s.find(nums[i-k]);
// cout << "del: " << *ite << endl;
s.erase(ite);
}
// cout << "Y: " << nums[i]<< " "<< s.size() << endl;
s.insert(nums[i]);
}
return false;
}
};
// 211. Add and Search Word - Data structure design
// https://leetcode.com/problems/add-and-search-word-data-structure-design/
class WordDictionary {
struct Node {
bool end;
vector<Node*> output;
Node(): output(26, nullptr), end(false) {}
};
vector<Node*> _heads;
public:
/** Initialize your data structure here. */
WordDictionary(): _heads(26, nullptr) {
}
/** Adds a word into the data structure. */
void addWord(string word) {
vector<Node*>* starts = &_heads;
int size = word.size();
for (int i = 0; i < size; ++i) {
char c = word[i];
int index = c - 'a';
if (!(*starts)[index]) {
(*starts)[index] = new Node;
}
if (i == size-1) (*starts)[index]->end = true;
starts = &((*starts)[index]->output);
}
}
/** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
bool search(string word) {
function<bool(int, vector<Node*>&)> sea = [&](int index, vector<Node*>& nodes) {
if (word[index] != '.') {
int pos = word[index] - 'a';
if (nodes[pos] == nullptr) return false;
else {
if (index == word.size() - 1) {
return nodes[pos]->end;
}
return sea(index+1, nodes[pos]->output);
}
} else {
for (int i = 0; i < 26; ++i) {
if (nodes[i] != nullptr) {
if (index == word.size() - 1) {
if (nodes[i]->end) return true;
} else {
bool res = sea(index+1, nodes[i]->output);
if (res) return res;
}
}
}
return false;
}
};
return sea(0, _heads);
}
};
/**
* Your WordDictionary object will be instantiated and called as such:
* WordDictionary* obj = new WordDictionary();
* obj->addWord(word);
* bool param_2 = obj->search(word);
*/
// 209. Minimum Size Subarray Sum
// https://leetcode.com/problems/minimum-size-subarray-sum/
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
// use prefix sum
partial_sum(begin(nums), end(nums), begin(nums));
int c = INT_MAX;
int size = nums.size();
int prev = 0;
for (int i = 0; i < size; ++i) {
int target = s + prev;
auto it = lower_bound(begin(nums), end(nums), target);
if (it == nums.end()) break;
int dis = distance(nums.begin(), it) - i + 1;
c = min(c, dis);
prev = nums[i];
}
return c == INT_MAX ? 0 : c;
}
int minSubArrayLenFast(int s, vector<int>& nums) {
int i = 0;
int j = 0;
int size = nums.size();
int sum = 0;
int c = INT_MAX;
while (true) {
while (j < size && sum < s) {
sum += nums[j];
++j;
}
if (sum < s) break;
int dis = j - i;
if (dis < c) c = dis;
sum -= nums[i];
++i;
}
return c == INT_MAX? 0 : c;
}
};
// 208. Implement Trie (Prefix Tree)
// https://leetcode.com/problems/implement-trie-prefix-tree/
class Trie {
struct TrieNode {
bool end;
vector<TrieNode*> out;
TrieNode(): end(false), out(26, nullptr) {}
};
vector<TrieNode*> _heads;
public:
/** Initialize your data structure here. */
Trie():_heads(26, nullptr) {
}
/** Inserts a word into the trie. */
void insert(string word) {
// cout << "Insert: " << word << endl;
function<void(const string&, int, vector<TrieNode*>&)> insert_helper = [&](
const string& word, int start, vector<TrieNode*>& heads
) {
if (start >= word.size()) return;
int index = word[start] - 'a';
if (!heads[index]) heads[index] = new TrieNode;
heads[index]->end = heads[index]->end || (start == word.size() - 1);
// cout << "char: " << word[start] << ", heads[index]->end: " << heads[index]->end << endl;
insert_helper(word, start+1, heads[index]->out);
};
insert_helper(word, 0, _heads);
}
/** Returns if the word is in the trie. */
bool search(string word) {
// cout << "Search: " << word << endl;
function<bool(const string&, int start, const vector<TrieNode*>&)> search_helper = [&](const string& word, int start, const vector<TrieNode*>& heads) {
int size = word.size();
int index = word[start] - 'a';
if (!heads[index]) return false;
if (size == start+1) {
return heads[index] && heads[index]->end;
} else {
return search_helper(word, start+1, heads[index]->out);
}
};
if (word.empty()) return true;
return search_helper(word, 0, _heads);
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
function<bool(const string&, int start, const vector<TrieNode*>&)> search_helper = [&](const string& word, int start, const vector<TrieNode*>& heads) {
int size = word.size();
int index = word[start] - 'a';
if (!heads[index]) return false;
if (size == start+1) {
return heads[index] != nullptr;
} else {
return search_helper(word, start+1, heads[index]->out);
}
};
if (prefix.empty()) return true;
return search_helper(prefix, 0, _heads);
}
};
/**
* Your Trie object will be instantiated and called as such:
* Trie* obj = new Trie();
* obj->insert(word);
* bool param_2 = obj->search(word);
* bool param_3 = obj->startsWith(prefix);
*/
// 207. Course Schedule
// https://leetcode.com/problems/course-schedule/
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
unordered_map<int, vector<int>> course; // id -> outputs
vector<bool> deps(numCourses, false);
for (vector<int>& dep: prerequisites) {
course[dep[1]].push_back(dep[0]);
deps[dep[0]] = true;
}
vector<bool> taken(numCourses, false);
unordered_set<int> s;
function<bool(int)> dfs = [&](int i) {
if (taken[i]) return false;
s.insert(i);
taken[i] = true;
for (int d : course[i]) {
if(!dfs(d)) return false;
}
taken[i] = false;
return true;
};
for (int i = 0; i < numCourses; ++i) {
if (deps[i]) continue;
if (!dfs(i)) return false;
}
return s.size() == numCourses;
}
};
// 1365. How Many Numbers Are Smaller Than the Current Number
// https://leetcode.com/problems/how-many-numbers-are-smaller-than-the-current-number/
class Solution {
public:
vector<int> smallerNumbersThanCurrent(vector<int>& nums) {
vector<int> bkp(nums);
sort(begin(bkp), end(bkp));
vector<int> result;result.reserve(nums.size());
for (int n : nums) {
auto ite = lower_bound(begin(bkp), end(bkp), n);
result.push_back(distance(bkp.begin(), ite));
}
return result;
}
};
// 1367. Linked List in Binary Tree
// https://leetcode.com/problems/linked-list-in-binary-tree/
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSubPath(ListNode* head, TreeNode* root) {
bool k = false, lr = false;
function<bool(ListNode*, TreeNode*, bool)> dfs = [&](
ListNode* head, TreeNode* root, bool cont
) {
if (!head) return true;
if (!root) return false;
if (cont) {
if (head->val != root->val) return false;
return dfs(head->next, root->left, true) || dfs(head->next, root->right, true);
}
if (head->val == root->val)
k = dfs(head->next, root->left, true) || dfs(head->next, root->right, true);
if (!k)
return dfs(head, root->left, false) || dfs(head, root->right, false);
return k;
};
return dfs(head, root, false);
}
};
// 1366. Rank Teams by Votes
// https://leetcode.com/problems/rank-teams-by-votes/
class Solution {
struct Vote {
char c;
array<int, 26> votes;
Vote(): c('0') {}
bool operator()(const Vote&l, const Vote& r) {
if (l.c == '0') return false;
if (r.c == '0') return true;
for (int i = 0; i < 26; ++i) {
if (l.votes[i] != r.votes[i])
return l.votes[i] > r.votes[i];
}
return l.c < r.c;
}
};
public:
string rankTeams(vector<string>& votes) {
int size = votes.size();
if (size == 1 || votes[0].size() == 1) return votes[0];
vector<Vote> v(26);
int team_size = votes[0].size();
for(string& vote: votes) {
for (int i = 0; i < team_size; ++i) {
char team = vote[i];
int t_id = team - 'A';
v[t_id].votes[i] += 1;
v[t_id].c = team;
}
}
sort(v.begin(), v.end(), Vote());
string s;
for (auto& vv: v) {
if (vv.c == '0') break;
s += vv.c;
}
return s;
}
};