---
# System prepended metadata

title: Grind 75 Week 3
tags: [grind75, week3]

---

###### tags: `grind75`, `week3`

# Grind 75 Week 3

# 1. Add Binary
:::success
- Time: $O(\text{max}(L_a, L_b)+1)$
- Space: $O(\text{max}(L_a, L_b)+1)$

| Runtime | 0 ms Beats 100% |
| --- | --- |
| Memory | 6.5 MB Beats 37.32% |

```cpp
class Solution {
public:
    string addBinary(string a, string b) {
        short carry=0;
        int size_a = a.size(), size_b = b.size();
        stringstream result;
        int ai=size_a-1, bi=size_b-1;
        while(carry || ai >= 0 || bi >= 0) {
          carry += (ai >= 0 ? a[ai] - '0' : 0) + (bi >= 0 ? b[bi] - '0' : 0);
          result << (carry%2);
          carry/=2;
          
          ai--; bi--;
        } 
        string answer = result.str();
        reverse(answer.begin(), answer.end());
        return answer;
    }
};
```
:::

:::info
# Solution1: BigInt

- TC: O(n)
- SC: O(n)

Explanations

1. Make `a` `b` be treated as binary number
    
    In JavaScript, the prefix **`0b`** is used to represent a binary number literal.
    
2. Use `BigInt` to  sum  `a` `b`  as normal number
    
    When we pass this string to the **`BigInt()`** function, it will be converted to a **`BigInt`** integer with the value **`10`**.
    
3. convert the result back to a binary string using the **`toString()`** method with a base of 2.

Why BigInt?

- **BigInt is used to represent Integers greater than 2^53 -1.**
    - The binary number may over the `2^53 - 1`(maximum of Number)

```jsx
var addBinary = function(a, b) {
    const aBin = `0b${a}`;
    const bBin = `0b${b}`;
    const sum = BigInt(aBin) + BigInt(bBin);
    return sum.toString(2);
};

// Example
// a = 11, b = 1
// aBin = 0b11, BigInt(aBin) = 3n
// bBin = 0b1, BigInt(bBin) = 1n
// sum = 4n
// sum.toString(2) = 100
```

---

# Solution2

- TC: O(n)
- SC: O(1)

Explanation

Why `parseInt(a.charAt(aLen--)`?

- extract the integer value of the current digit in the binary string **`a`** at position **`aLen`**, and decrement **`aLen`**to move to the next digit in the next iteration of the while loop.

```jsx
var addBinary = function(a, b) {
    let aLen = a.length - 1;
    let bLen = b.length - 1;
    let carry = 0;
    let result = "";

    while (aLen >= 0 || bLen >= 0 || carry > 0) {
        let sum = carry;
        if (aLen >= 0) sum += parseInt(a.charAt(aLen--));
        if (bLen >= 0) sum += parseInt(b.charAt(bLen--));
		// Calculate the binary digit value of the current sum by taking sum modulo 2
		// and prepend it to the result string. ( + result is prepend)
        result = (sum % 2) + result;
        carry = Math.floor(sum / 2);
    }

    return result;
};
```
:::
# 2. Diameter of Binary Tree
:::success
- Time: $O(N)$
- Space: $O(N)$

| Runtime | 3 ms Beats 98.73% |
| --- | --- |
| Memory | 20.9 MB Beats 8.85% |

```cpp
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int diameterOfBinaryTree(TreeNode* root) {
       if(!root) return 0;
       
       int d=0;
       height(root, d);
       return d;
    }
    int height(TreeNode* root, int &d) {
      if(!root) return 0;
      
      int l = height(root->left, d);
      int r = height(root->right, d);
      d = max({d, l+r});
      return 1 + max({l, r});
    }
};
```
:::

:::info
# Solution1: BFS
- TC: O(n^2)
- SC: O(n)
```javascript=
var diameterOfBinaryTree = function(root) {
    if (!root) return 0;

    let max = 0;
    let queue = [root];

    while (queue.length) {
        let node = queue.shift();

        let leftDepth = getDepth(node.left);
        let rightDepth = getDepth(node.right);

        max = Math.max(max, leftDepth + rightDepth);

        if (node.left) queue.push(node.left);
        if (node.right) queue.push(node.right);
    }

    return max;
};

// Asscoiated w/ 104. max depth
function getDepth(node) {
    if (!node) return 0;

    return Math.max(getDepth(node.left), getDepth(node.right)) + 1;
}
```

# Solution2: DFS

- TC: O(n)
- SC: O(n)
```jsx
var diameterOfBinaryTree = function(root) {
    if (!root) return 0;
    let max = 0;

    function getHeight(node) {
        if (!node) return 0;

        let leftHeight = getHeight(node.left);
        let rightHeight = getHeight(node.right);
        
        max = Math.max(leftHeight + rightHeight, max);

        return Math.max(leftHeight, rightHeight) + 1;
    }

    getHeight(root);

    return max;
};
```
:::
# 3. Middle of the Linked List
:::success
Time: O(N)
Space: O(1)
```cpp!
/**
 * 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* middleNode(ListNode* head) {
        if(!head->next) return head;

        ListNode * slow= head, * fast=head;
        
        while(fast->next && fast->next->next) {
          slow = slow->next;
          fast = fast->next->next;
        }

        if(fast->next) return slow->next;

        return slow;
    }
};
```
:::

:::info
# Solution1: Fast & Slow Pointers ( One Pass )
When **`fast`** reaches the end of the linked list, **`slow`** will be at the middle node of the linked list.

1. Start with two pointers **`slow`** and **`fast`** at the head of the linked list.
2. Move **`slow`**one step at a time, and **`fast`** two steps at a time.

- TC: O(n)
- SC: O(1)
    - we only need to use two pointers **`slow`**
     and **`fast`**.

```jsx
var middleNode = function(head) {
    let fast = head;
    let slow = head;

    while (fast && fast.next) {
        slow = slow.next;
        fast = fast.next.next;
    }

    return slow;
};
```

---

# Solution2: Brute Force ( Two Pass )
Get the length of linked-list, then find the middle.

- TC: O(n)
- SC: O(1)

```jsx
var middleNode = function(head) {
	let count = 0;
	let current = head;

	while (current) {
		count++;
		current = current.next;
	}

	// 中間值有兩個時，直接取下一個，所以無條件進位。
	let middle = Math.floor(count/2);
	current = head;
	for (let i = 0; i < middle; i++) {
		current = current.next;
	}

	return current;
}
```
:::
# 4. Maximum Depth of Binary Tree
:::success
**4 ms** Beats **93.18%**

**18.7 MB** Beats **93.34%**

- Time: $O(n)$：
    - 如果 skewed，一整條走過就會是 n
- Space: $O(n)$：
    - 如果 skewed，一整條走過當下 stack 最多有 n 個 dfs

# Code

```cpp
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int dfs(TreeNode* root, int depth) {
      if(!root) {
        return depth;
      }
      int left=depth, right=depth;
      if(root->left) {
        left = dfs(root->left, depth+1);
      }
      
      if(root->right) {
        right = dfs(root->right, depth+1);
      }
      return max(left, right);
    }
    int maxDepth(TreeNode* root) {
      if(!root) return 0;
      
      return dfs(root, 1);
    }
};
```
:::

:::info
# Solution1: DFS

- TC: O(n)
- SC: O(n)

```jsx
var maxDepth = function(root) {
    if (!root) return 0;
    
    return getHeight(root);
};

function getHeight(node) {
    if (!node) return 0;

    let leftHeight = getHeight(node.left);
    let rightHeight = getHeight(node.right);

    return Math.max(leftHeight, rightHeight) + 1;
}

// Cleaner
var maxDepth = function(root) {
    if(!root) return 0;
    return Math.max(maxDepth(root.left),maxDepth(root.right)) + 1;
};
```

---

# Solution2: BFS

- TC: O(n)
- SC: O(n)

```jsx
var maxDepth = function(root) {
    if (!root) return 0;

    let levels = 0, queue = [root];

    while (queue.length) {
				// 沒有鎖定的 levelSize，直接在 for loop 中使用 queue.length 的話會變成在計算每層 node 的數量
  			let levelSize = queue.length;

        // BFS 的方式 iterate 每個 node
        for (let i = 0; i < levelSize; i++) {
            let node = queue.shift();

            // 進入下一層，沒得 push 時，代表該 node 的 左 or 右 是空的
            if (node.right) queue.push(node.right);
            if (node.left) queue.push(node.left); 
        }

        levels++;
    }

    return levels;
};
```
:::
# 5. Contains Duplicate
:::success
T: O(N)
S: O(N)
```cpp!
class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        unordered_map<int, bool> seen;
       for(auto &e : nums) {
         if(seen.count(e)) return true;

         seen[e] = true;
       }
       return false;
    }
};
```
:::

:::info
# Solution1: Hash Table

- TC: O(n)
- SC: O(n)

```jsx
var containsDuplicate = function(nums) {
    const map = new Map();

    for (const num of nums) {
        if (map.has(num)) return true;

        map.set(num , 1);
    }

    return false;
};
```
:::