# Leetcode summary of 20200223-20200301

Posted by chunyang on March 1, 2020

### Summary

Solved problems list

• 187. Repeated DNA Sequences
• 201. Bitwise AND of Numbers Range
• 166. Fraction to Recurring Decimal
• 146. LRU Cache
• 131. Palindrome Partitioning
• 91. Decode Ways
• 498. Diagonal Traverse
• 518. Coin Change 2
• 133. Clone Graph
• 1361. Validate Binary Tree Nodes
• 264. Ugly Number II
• 236. Lowest Common Ancestor of a Binary Tree

### Highlight

#### Bitwise AND of Numbers Range

It is similar to the problem of counting the number of 1s in a number. For any number n, the way to remove the last bit of 1 in n is:

n = n & (n-1)


The largest number by performing AND is the number itself. So we keep repeating this process until we can no no more. The remained n is the final result.

#### Coin change

It is one kind of knapsack problem. You can refer to knapsack

### Code Section

The sequence of code is the same with the problem list.

// 187. Repeated DNA Sequences
// https://leetcode.com/problems/repeated-dna-sequences/
class Solution {
public:
vector<string> findRepeatedDnaSequences(string s) {
int size = s.size();
unordered_map<string, int> m;
set<string> ss;
for (int i = 0; i < size; ++i) {
auto sub = s.substr(i, 10);
if (ss.find(sub) != ss.end()) continue;
if (m.find(sub) == m.end()) {
m[sub] = i;
} else {
ss.insert(sub);
}
}
return vector<string>(ss.begin(), ss.end());
}
};

// 201. Bitwise AND of Numbers Range
// https://leetcode.com/problems/bitwise-and-of-numbers-range/
class Solution {
public:
int rangeBitwiseAnd(int m, int n) {
if (m == n) return m;
if (m == 0 || n == 0) return 0;
while (true) {
if (n > m) n &= (n-1);
else break;
}
return n;
}
};

// 166. Fraction to Recurring Decimal
// https://leetcode.com/problems/fraction-to-recurring-decimal/
class Solution {
public:
string fractionToDecimal(int numerator, int denominator) {
map<int, int> pos;
string result;
long long n = numerator;
long long d = denominator;
bool flag = false;
if (n < 0 && d < 0) {
n = -n;
d = -d;
} else if (n < 0) {
flag = true;
n = -n;
} else if (d < 0) {
flag = true;
d = -d;
}
if (n == 0) return "0";
int p = -1;
while (n) {
if (n % d == 0) {
result += to_string(n / d);
break;
} else {
if (n < d) {
if (result.empty()) result += "0";
result += ".";
p = result.size();
}
if (pos[n] != 0) {
// find repeat pattern
result += ")";
result.insert(pos[n], "(");
break;
}
pos[n] = p;
n *= 10;
auto div = n / d;
auto r = n % d;

n = r;
result += to_string(div);
++p;
} else {
result += to_string(n/d);
n = n % d;
}
}
}
return flag ? "-" + result : result;
}
};

// 146. LRU Cache
// https://leetcode.com/problems/lru-cache/
struct MyNode {
MyNode* prev;
MyNode* next;
int val;
int key;
MyNode(int key, int val):key(key), val(val), prev(nullptr), next(nullptr) {}
};
class LRUCache {
unordered_map<int, MyNode*> _indexer;
int size;
int cap;
MyNode* tail;
public:
LRUCache(int capacity): size(0), head(nullptr), tail(nullptr), cap(capacity) {
}

int get(int key) {
if (_indexer.empty() || _indexer.find(key) == _indexer.end()) {
return -1;
}
auto pos = _indexer[key];
if (pos == tail) tail = pos->prev;
auto prev = pos->prev;
if (prev) {
prev->next = pos->next;
if (pos->next) pos->next->prev = prev;
}
pos->next = next;
next->prev = pos;
/*
cout << "----------getting: " << key << endl;
while (t) {
cout << "key: " << t->key << " val: " << t->val << endl;
t = t->next;
}
cout << "head: " << head->key << " tail: " << tail->key << endl;
if (tail->prev) {
cout << "tail->prev: " << tail->prev->key << endl;
} else {
cout << "tail->prev is nullptr" << endl;
}
*/
}

void put(int key, int value) {
if (_indexer.find(key) != _indexer.end()) {
get(key);
} else {
auto n = new MyNode(key, value);
++size;
if (size > cap) {
auto pos = tail;
tail = tail->prev;
if (tail == nullptr) head = tail = nullptr;
else tail->next = nullptr;
--size;
_indexer.erase(pos->key);
delete pos;
}
} else {
tail = n;
}
_indexer[key] = n;
}
/*
cout << "----------Putting: " << key << " val: " << value << endl;
while (t) {
cout << "key: " << t->key << " val: " << t->val << endl;
t = t->next;
}
cout << "head: " << head->key << " tail: " << tail->key << endl;
*/
}
};

/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache* obj = new LRUCache(capacity);
* int param_1 = obj->get(key);
* obj->put(key,value);
*/

// 131. Palindrome Partitioning
// https://leetcode.com/problems/palindrome-partitioning/
class Solution {
public:
vector<vector<string>> partition(string s) {
function<bool(int, int)> is_palindrome = [&](int start, int end) {
while (start < end && s[start] == s[end]) {
++start;
--end;
}
return start >= end;
};
vector<vector<string>> result;
vector<string> path;
int size = s.size();
function<void(int)> dfs = [&](int start) {
if (start == size) {
result.push_back(path);
}
for (int i = start; i < size; ++i) {
if (is_palindrome(start, i)) {
path.push_back(s.substr(start, i-start+1));
dfs(i+1);
path.pop_back();
}
}
};
dfs(0);
return result;
}
};

// 91. Decode Ways
// https://leetcode.com/problems/decode-ways/
class Solution {
public:
int numDecodings(string s) {
int size = s.size();
vector<int> dp(size+1);
dp[0] = 1;
dp[1] = 1;
if (s[0] == '0') return 0;
for (int i = 2; i <= size; ++i) {
bool good = false;
if (s[i-1] != '0') {
dp[i] = dp[i-1];
good = true;
}
if (s[i-2] == '1' || (s[i-2] == '2' && s[i-1] <= '6')) {
dp[i] += dp[i-2];
good = true;
}
if (!good) return 0;
}
return dp[size];
}
};

// 498. Diagonal Traverse
// https://leetcode.com/problems/diagonal-traverse/
class Solution {
public:
vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
vector<int> result;
int m = matrix.size();
if (m == 0) return result;

int n = matrix[0].size();
result.reserve(m*n);
bool reversed = true;
for (int i = 0; i < n; ++i) {
vector<int> mid;
for (int r = 0, c = i; r < m && c >= 0; ++r, --c) {
mid.push_back(matrix[r][c]);
}
if (reversed) {
copy(mid.rbegin(), mid.rend(), back_inserter(result));
} else {
copy(mid.begin(), mid.end(), back_inserter(result));
}
reversed = !reversed;

}
for (int i = 1; i < m; ++i) {
vector<int> mid;
for (int r = i, c = n-1; r < m && c >= 0; ++r, --c) {
mid.push_back(matrix[r][c]);
}
if (reversed) {
copy(mid.rbegin(), mid.rend(), back_inserter(result));
} else {
copy(mid.begin(), mid.end(), back_inserter(result));
}
reversed = !reversed;

}
return result;
}
};

// 518. Coin Change 2
// https://leetcode.com/problems/coin-change-2/
class Solution {
public:
int change(int amount, vector<int>& coins) {
vector<int> dp(amount + 1, 0);
dp[0] = 1;
for (const int coin : coins)
for (int i = 0; i <= amount - coin; ++i)
dp[i + coin] += dp[i];
return dp[amount];
}
};

/**
* 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:

vector<TreeNode*> generateTrees(int n) {
unordered_map<string, vector<TreeNode*>> cache;
function<vector<TreeNode*>(int, int )> gen = [&](int s, int e) {
vector<TreeNode*> result;
if (s > e) result.push_back(nullptr);
else if (s == e) result.push_back(new TreeNode(s));
else {
for (int i = s; i <= e; ++i) {
auto l = gen(s, i-1);
auto r = gen(i+1, e);
for (auto ll : l) {
for (auto rr : r) {
TreeNode* node = new TreeNode(i);
node->left = ll;
node->right = rr;
result.push_back(node);
}
}
}
}
return result;
};
if (n == 0) return vector<TreeNode*>();
return gen(1, n);
}
};

// 133. Clone Graph
// https://leetcode.com/problems/clone-graph/
/*
// Definition for a Node.
class Node {
public:
int val;
vector<Node*> neighbors;

Node() {
val = 0;
neighbors = vector<Node*>();
}

Node(int _val) {
val = _val;
neighbors = vector<Node*>();
}

Node(int _val, vector<Node*> _neighbors) {
val = _val;
neighbors = _neighbors;
}
};
*/
class Solution {
public:
Node* cloneGraph(Node* node) {
unordered_map<int, Node*> cloned;
function<Node*(Node*)> clone_one = [&](Node* node) {
if (!node) return node;
if (cloned.find(node->val) != cloned.end()) return cloned[node->val];
Node* cloned_node = new Node(node->val);
cloned[node->val] = cloned_node;
for (Node* n : node->neighbors) {
cloned_node->neighbors.push_back(clone_one(n));
}
return cloned_node;
};
return clone_one(node);
}
};

// 1361. Validate Binary Tree Nodes
// https://leetcode.com/problems/validate-binary-tree-nodes/
class Solution {
public:
bool validateBinaryTreeNodes(int n, vector<int>& leftChild, vector<int>& rightChild) {
// more than one root
// more than two child
// more than two parent
unordered_set<int> roots;
unordered_set<int> children;
function<bool(int)> be_child = [&](int n) {
if (n == -1) return true;
auto b = children.find(n) == children.end();
if (b) {
children.insert(n);
}
return b;
};
function<void(int)> del = [&](int n) {
if (n == -1) return;
if (roots.find(n) != roots.end()) {
roots.erase(n);
}
};
for (int i = 0; i < n; ++i) {
auto l = leftChild[i];
auto r = rightChild[i];
auto b1 = be_child(l); auto b2 = be_child(r);
del(l); del(r);
if (!b1 || !b2) return false;
/*
cout << "for i = " << i << " root: ";
copy(begin(roots), end(roots), ostream_iterator<int>(cout, ","));
cout << endl;
cout << "children: ";
copy(begin(children), end(children), ostream_iterator<int>(cout, ","));
cout << endl;
*/

if (children.find(i) == children.end()) {
roots.insert(i);
} else {
if (roots.find(i) != roots.end()) {
roots.erase(i);
}
}
}
// cout << "roots.size(): " << roots.size() << endl;
return roots.size() == 1;
}
};

// 264. Ugly Number II
// https://leetcode.com/problems/ugly-number-ii/
class Solution {
public:
int nthUglyNumber(int n) {
vector<int> l(n); // initialize the squence.
int p_2, p_3, p_5; // initialize the pointer
l[0] = 1;
p_2 = 0;
p_3 = 0;
p_5 = 0;
for (int i = 1; i < n; ++i) {
l[i] = min({l[p_2] * 2, l[p_3] * 3, l[p_5] * 5});
if (l[p_2] * 2 == l[i]) ++p_2;
if (l[p_3] * 3 == l[i]) ++p_3;
if (l[p_5] * 5 == l[i]) ++p_5;
}
return l[n - 1];
}
public:
bool isUglyNumber(int num) {
if (num <= 0) return false;
while (num % 6 == 0) num /= 6;
while (num % 10 == 0) num /= 10;
while (num % 15 == 0) num /= 15;
while (num % 2 == 0) num /= 2;
while (num % 3 == 0) num /= 3;
while (num % 5 == 0) num /= 5;
return num == 1;

}
int nthUglyNumberSlow(int n) {
int cnt = 0;
int i = 1;
while (cnt < n) {
if (isUglyNumber(i)) ++cnt;
++i;
}
return i-1;
}
};

// 236. Lowest Common Ancestor of a Binary Tree
// https://leetcode.com/problems/lowest-common-ancestor-of-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:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (!root) return nullptr;
if (root->val == p->val || root->val == q->val) return root;
auto n = lowestCommonAncestor(root->left, p, q);
auto m = lowestCommonAncestor(root->right, p, q);
if (m && n) return root;
else if (m) return m;
else if (n) return n;
else return nullptr;
}
};