---
# System prepended metadata

title: Week2 - Dynamic Programming
tags: [Leetcode]

---

# Week2 - Dynamic Programming 

###### tags: `Leetcode`

## 5. Longest Palindromic Substring
思路：定義指針 $i, j$ 分別代表子字串的起始與終止位置，並定義陣列 $table$，起始位置為 $i$ 終止位置為 $j$ 的子字串為對稱的，$table[i][j]=True$，否則，$table[i][j]=False$，由此可知，陣列 $table$ 滿足下列性質：
+ $table[i][i] = 1$。
+ 若 $s[i] == s[j]$ 且 $table[i+1][j-1] = True$，則 $table[i][j] = True$。 
+ 若 $s[i] == s[j]$ 且 $j == i+1$，則 $table[i][j] = True$。
![](https://i.imgur.com/RMGttcB.png)
```python
class Solution:
    def longestPalindrome(self, s: str) -> str:
        l = len(s)
        save_list = [False] * l
        max_length, target_tuple = 0, (-1, -1)
        
        for j in range(l): 
            for i in range(j + 1):
                if i == j or (s[i] == s[j] and (j == i+1 or save_list[i+1])): 
                    save_list[i] = True
                    if j - i + 1 > max_length: 
                        max_length = j - i + 1 
                        target_tuple =  (i, j)
                else: 
                    save_list[i] = False
        return s[target_tuple[0]: target_tuple[1]+1]     
```
+ Ping-Hsuan's solution
```python
class Solution:
    def longestPalindrome(self, s: str) -> str:
        res = ''
        resLen = 0
        
        for i in range(len(s)):
            # Odd length
            l, r = i, i
            while l >=0 and r < len(s) and s[l] == s[r]:
                if (r-l+1) > resLen:
                    res = s[l:r+1]
                    resLen = r-l+1
                l -= 1
                r += 1
            # Even legnth
            l, r = i, i+1
            while l >= 0 and r < len(s) and s[l] == s[r]:
                if (r-l+1) > resLen:
                    res = s[l:r+1]
                    resLen = r-l+1
                l -= 1
                r += 1 
        return res
```

+ **Links**
  + https://www.youtube.com/watch?v=ZnzvU03HtYk

## 70. Climbing Stairs
定義函數 $\phi(k)=$ 走 k 步的所有組合。我們知道 $\phi(k)$ 滿足下列性質：
$$ \phi(n)=\left\{
\begin{array}{rcl}
&\phi(n-1) + \phi(n-2)&,  &   & {n>=2}\\
&1&,     &      & {n<2}
\end{array} \right. $$

```python
class Solution:
    def climbStairs(self, n: int) -> int:
        ways = [1, 1] 
        for i in range(2, n+1):
            ways.append(ways[i-1] + ways[i-2])
        return ways[-1]
```




## 64. Minimum Path Sum



![](https://i.imgur.com/ItpX6rW.png)


```python
class Solution:
    def minPathSum(self, grid: List[List[int]]) -> int:
        m, n = len(grid), len(grid[0])
        last_min_array = [0] * n 
        last_min_array[0] = grid[0][0]
        
        for i in range(1, n):
            last_min_array[i] = last_min_array[i-1] + grid[0][i] 
        
        for i in range(1, m): 
            for j in range(n):
                if j == 0:  
                    last_min_array[j] = last_min_array[0] + grid[i][j]
                else: 
                    last_min_array[j] = min(last_min_array[j-1], last_min_array[j]) + grid[i][j]
                    
        return last_min_array[-1]
```


## 62. Unique Paths
我們知道所有的組合數滿足 $C^{n+m-2}_{n-1}$ 的公式。

![](https://i.imgur.com/Zh2LC9x.png)

```python
class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        return self.combinatory(m+n-2, min(m,n)-1) 
    
    def combinatory(self, n, k):
        numerator, deniminator = 1, 1
        for i in range(n, n-k, -1): 
            numerator *= i
            
        for i in range(2, k+1): 
            deniminator *= i
        
        return int(numerator/deniminator) 
```

## 53. Maximum Subarray
```python
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        max_sum, curr_sum = nums[0], 0   
        for ele in nums: 
            curr_sum = curr_sum + ele
            max_sum = max(max_sum, curr_sum)
            if curr_sum < 0: 
                curr_sum = 0 
        return max_sum 
```
Ping-Hsuan Q: How do we prove this?, how about divide and conquer?

+ **Links**
  + divide and conquer： https://www.youtube.com/watch?v=3GD-3UZGsVI&t



## 63. Unique Paths II
![](https://i.imgur.com/FoabsLA.png)

```python
class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        m, n = len(obstacleGrid), len(obstacleGrid[0])
        last_res = [1 - obstacleGrid[0][0]] * n 
        
        for j in range(1, n):
            last_res[j] =  last_res[j-1] if obstacleGrid[0][j] == 0 else 0
        
        for i in range(1, m): 
            if obstacleGrid[i][0] == 1: 
                last_res[0] = 0 
            for j in range(1, n):
                last_res[j] = last_res[j-1] + last_res[j] if obstacleGrid[i][j] == 0 else 0 
        return last_res[-1]
```

