# Top interview 150
## 88. Merge Sorted Array
```c=
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i = m-1;
int j = n-1;
int insert_index = m+n-1;
while(i>=0 && j>=0){
if(nums2[j]>=nums1[i]){
nums1[insert_index] = nums2[j];
j--;
}
else{
nums1[insert_index] = nums1[i];
i--;
}
insert_index--;
//cout<<i<<" "<<j<<" "<<insert_index<<endl;
}
while(j>=0){
nums1[insert_index] = nums2[j];
insert_index--;
j--;
}
}
};
```
### Notes:
1. 用two-pointers來解
2. 兩個指標都先指向vector內的最後一個元素(Maxima)
3. 比較大的那個就放在nums1的最後一個,重複此步驟一直比大小
4
---
## 121. Best Time to Buy and Sell Stock
```c=
class Solution {
public:
int maxProfit(vector<int>& prices) {
int max_profit = 0;
int buy_index = 0, sell_index = 1;
int temp = 0;
for(sell_index=1; sell_index<prices.size(); sell_index++){
temp = prices[sell_index] - prices[buy_index];
if(temp>max_profit)
max_profit = temp;
if(temp<0){
buy_index = sell_index;
}
}
return max_profit;
}
};
```
### Notes:
1. 用two-pointers計算獲利,sell_index是主要在變動的
2. 唯有當temp_profit < 0,才會改變buy_index(代表當下這個index便宜,更適合當buy_index)
---
## 122. Best Time to Buy and Sell Stock II
```c=
class Solution {
public:
int maxProfit(vector<int>& prices) {
int b_index = 0, s_index = 1;
int max_profit = 0, sum = 0, temp = 0, pre_max = 0;
for(s_index = 1; s_index < prices.size(); s_index++){
temp = prices[s_index] - prices[b_index];
if(temp > max_profit){
sum-=pre_max;
max_profit = temp;
sum+=max_profit;
pre_max = max_profit;
}
if(temp < 0 || temp<max_profit){
b_index = s_index;
max_profit = 0; pre_max = 0;
}
}
return sum;
}
};
```
### Notes:
1. 跟Best Time to Buy and Sell Stock差不多,先找出max_profit
2. 但因為可以重複買賣,所以若發現temp < 0,就可以再買賣一次,所以這題其實就是重複找很多次max_profit
---
## 36. Valid Sudoku
```c=
class Solution {
public:
bool isValidSudoku(vector<vector<char>>& board) {
// check row
for(int i=0; i<9; i++){
unordered_set<char> row_record;
for(int j=0; j<9; j++){
if(board[i][j]!='.'&&row_record.find(board[i][j])!=row_record.end())
return false;
row_record.insert(board[i][j]);
}
}
// check col
for(int i=0; i<9; i++){
unordered_set<char> col_record;
for(int j=0; j<9; j++){
if(board[j][i]!='.'&&col_record.find(board[j][i])!=col_record.end())
return false;
col_record.insert(board[j][i]);
}
}
// check 3x3 subboxes
vector<unordered_set<char>> record(9);
for(int i=0; i<9; i++){
for(int j=0; j<9; j++){
int number = 3*(int(i/3)) + int(j/3);
if(board[i][j]!='.'&&record[number].find(board[i][j])!=record[number].end())
return false;
record[number].insert(board[i][j]);
}
}
return true;
}
};
```
### Notes:
1. 這題只是要判斷是不是一個有效的數獨,只需要按照題目說的規則檢查即可,不需要考慮可能的解
2. 依序檢查每個row有無重複、每個col有無重複、每個3x3的box內有無重複。
---
## 12. Integer to Roman
```c=
class Solution {
public:
string intToRoman(int num) {
vector<int> nums = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
vector<string> roman = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
string ans = "";
for(int i=0; i<nums.size(); i++){
if(num>=nums[i]){
for(int j=0; j<int(num/nums[i]); j++)
ans+=roman[i];
num = num%nums[i];
}
}
return ans;
}
};
```
### Notes:
1. 因為題目說的特殊情況只有6種,所以先事先pre-define這幾個對應的roman即可
---
## 73. Set Matrix Zeroes
```c=
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int* r_record = new int[matrix.size()]{};
int* c_record = new int[matrix[0].size()]{};
for(int i=0; i<matrix.size(); i++){
for(int j=0; j<matrix[0].size(); j++){
if(matrix[i][j] == 0){
r_record[i] = 1;
c_record[j] = 1;
}
}
}
for(int i=0; i<matrix.size(); i++){
for(int j=0; j<matrix[0].size(); j++){
if(r_record[i] == 1 || c_record[j] == 1){
matrix[i][j] = 0;
}
}
}
}
};
```
### Notes:
1. 新增2個array,分別記錄第i-th個row是否全為0、第i-th個col是否全為0
2. 這個做法就不需要花費O(MxN)的space來儲存是否為0
---
## 61. Rotate List
```c=
/**
* 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:
ListNode* rotateRight(ListNode* head, int k) {
if(head==NULL)
return NULL;
ListNode* temp = head;
ListNode* pre = NULL;
int length = 0;
while(temp!=NULL){
length++;
pre = temp;
temp = temp->next;
}
temp = head;
if(k%length == 0)
return head;
int new_k = length - (k%length);
for(int i=0; i<new_k-1; i++)
temp = temp->next;
ListNode* new_root = temp->next;
pre->next = head;
temp->next = NULL;
return new_root;
}
};
```
### Notes:
1. 先count出整個List的長度
2. 這題其實不用step by step的插入,只需要找出"切斷的地方",把整段list移動到head前面即可
3. 因為k可能遠大於list.length(),所以要取Mod
4. Time complexity O(N)
---
## 219. Contains Duplicate II
```c=
class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k) {
if(nums.size() == 1)
return false;
map<int, vector<int>> loc;
for(int i=0; i<nums.size(); i++){
loc[nums[i]].push_back(i);
}
for(auto it = loc.begin(); it!=loc.end(); it++){
for(int i=0; i<loc[it->first].size()-1; i++){
if(abs(loc[it->first][i] - loc[it->first][i+1])<=k)
return true;
}
}
return false;
}
};
```
### Notes:
1. 用c++的stl來解,紀錄每個num出現的index
---
## 71. Simplify Path
```c=
class Solution {
public:
string simplifyPath(string path) {
vector<string> strs;
stack<string> s;
string ans = "";
string temp = "";
if(path[path.length()-1]!='/')
path = path + "/";
for(int i=0; i<path.length()-1; i++){
if (path[i]!='/'){
temp = temp + path[i];
if(path[i+1] == '/'){
strs.push_back(temp);
temp = "";
}
}
}
for(int i=0; i<strs.size(); i++){
if(strs[i] == "."){
continue;
}
else if(strs[i] == ".."){
if(s.size()!=0)
s.pop();
}
else{
s.push(strs[i]);
}
}
while(s.size()!=0){
ans = "/" + s.top() + ans;
s.pop();
}
return ans.length()==0?"/":ans;
}
};
```
### Notes:
1. 從題目可以發現,不論是幾個"/"都不影響,所以遇到"/"可以忽略
2. split path string by "/"
3. 假設path = "/home/../file/", 那strs = {"home", "..", file"}
4. 建立一個stack,若遇到folder name就放入stack,遇到".."要特別注意,就把stack的top value移除即可。
---
## 933. Number of Recent Calls
```c=
class RecentCounter {
public:
queue<int> q;
RecentCounter() {
q = queue<int>();
}
int ping(int t) {
int retv = 0;
q.push(t);
while(true){
if(q.front() >= t-3000){
retv = q.size();
break;
}
else{
q.pop();
}
}
return retv;
}
};
/**
* Your RecentCounter object will be instantiated and called as such:
* RecentCounter* obj = new RecentCounter();
* int param_1 = obj->ping(t);
*/
```
### Notes:
1. 其實這題用brute force硬解也可以過 O(N)
2. 但因為他有告訴你t只會越來越大(等於queue是有排序)
3. 我們只要檢查q.front()有沒有大於t-3000即可,若沒有則pop出來
4. 最終的結果就是q.size()
---
## 649. Dota2 Senate
```c=
class Solution {
public:
string predictPartyVictory(string senate) {
queue<int> radiant_queue, dire_queue;
for(int i=0; i<senate.length(); i++){
if(senate[i] == 'R')
radiant_queue.push(i);
else
dire_queue.push(i);
}
while(radiant_queue.size()!=0 && dire_queue.size()!=0){
int r_index = radiant_queue.front();
radiant_queue.pop();
int d_index = dire_queue.front();
dire_queue.pop();
//代表D會被ban掉,把R重新丟回queue裡面
if(r_index < d_index){
radiant_queue.push(r_index + senate.length());
}
else{
dire_queue.push(d_index + senate.length());
}
}
return (radiant_queue.size()==0)?"Dire":"Radiant";
}
};
```
### Notes:
1. 這題的解法很漂亮
2. 因為會有順序的關係,queue裡面存的是index
3. R_index < D_index,代表R一定可以把D給ban了
4. R_index因為還有下一輪,所以還要重新放回queue (line 19)