# Posts published in January 2019

On an N x N grid, each square grid[i][j] represents the elevation at that point (i,j).

Now rain starts to fall. At time t, the depth of the water everywhere is t. You can swim from a square to another 4-directionally adjacent square if and only if the elevation of both squares individually are at most t. You can swim infinite distance in zero time. Of course, you must stay within the boundaries of the grid during your swim.

You start at the top left square (0, 0). What is the least time until you can reach the bottom right square (N-1, N-1)?

Example 1:

Input: [[0,2],[1,3]]
Output: 3
Explanation:
At time 0, you are in grid location (0, 0).
You cannot go anywhere else because 4-directionally adjacent neighbors have a higher elevation than t = 0.

You cannot reach point (1, 1) until time 3.
When the depth of water is 3, we can swim anywhere inside the grid.


Example 2:

Input: [[0,1,2,3,4],[24,23,22,21,5],[12,13,14,15,16],[11,17,18,19,20],[10,9,8,7,6]]
Output: 16
Explanation:
0  1  2  3  4
24 23 22 21  5
12 13 14 15 16
11 17 18 19 20
10  9  8  7  6

The final route is marked in bold.
We need to wait until time 16 so that (0, 0) and (4, 4) are connected.


Note:

1. 2 <= N <= 50.
2. grid[i][j] is a permutation of [0, …, N*N – 1].

## Solution 1: Dijkstra’s Algorithm

Time complexity: O(n^2*logn)
Space complexity: O(n^2)

## Solution 2: Binary Search + BFS

Time complexity: O(2logn * n^2)
Space complexity: O(n^2)

## C++

Segment tree is a balanced binary tree with O(logn) height given n input segments.
Segment tree supports fast range query O(logn + k), and update O(logn).
Building such a tree takes O(n) time if the input is an array of numbers.

Tree之所以大行其道就是因为其结构和人类组织结构非常接近。就拿公司来说好了，CEO统领全局(root)，下面CTO，CFO等各自管理一个部门，每个部门下面又正好有好两个VP，每个VP下面又有两个director，每个director下面又有2个manager，每个manager下面又有2个底层员工(leaf)，为什么是2？因为我们用二叉树啊~

nums = [1, 3, 5]，
sumRange(0, 2) = 1+3+5 = 9
update(1, 2) => [1, 2, 5]
sumRange(0, 2) = 1 + 2 + 5 = 7

sumRange(i, j) := sums[j] – sums[i – 1] if i > 0 else sums[j]

Update: O(logn)，Query: O(logn+k)

root存储的是所有元素的和。

start #起始范围
end #终止范围
mid #拆分点，通常是 (start + end) // 2
val #所有子元素的和
left #左子树
right #右子树

Update: 由于每次只更新一个元素的值，所以CEO知道这个员工是哪个人管的，派发下去就行了，然后把新的结果再返回回来。

T(n) = T(n/2) + 1 => O(logn)

Query: query的range可以是任意的，就有以下三种情况：

case 1: 这个range正好和我负责的range完全相同。比如sumQuery(CTO, 0, 99)，这个时候CTO直接返回已经求解过的所有下属的和即可。

case 2: 这个range只由我其中一个下属负责。比如sumQuery(CEO, 0, 10)，CEO知道0~10全部由CFO负责，那么他就直接返回sumQuery(CTO, 0, 10)。

case 3: 这个range覆盖了我的两个下属，那么我就需要调用2次。比如sumQuery(CEO, 80, 120)，CEO知道0~99由CTO管，100~199由CFO管，所以他只需要返回：

sumQuery(CTO, 80, 99) + sumQuery(CFO, 100, 120)

Query需要访问到的节点数量的worst和average case。Worst case 大约访问 4*logn – 3 个节点，这个数字远远小于n。和n成对数关系。

CEO管200人，那么就找2个人(CTO，CFO各管100人。CTO管100人，再找2个VP各管50人，以此类推，直到manager管2个人，2个人都是底层员工(leaf)，没有人管（双关）。

CEO = buildTree(0, 199)

CEO.left # CTO 负责0~99
CEO.right # CFO 负责100~199

Query: # of nodes visited: Average and worst are both ~O(logn)

## Applications

LeetCode 307 Range Sum Query – Mutable

## Python3

Given two integers A and B, return any string S such that:

• S has length A + B and contains exactly A 'a' letters, and exactly B 'b' letters;
• The substring 'aaa' does not occur in S;
• The substring 'bbb' does not occur in S.

Example 1:

Input: A = 1, B = 2
Output: "abb"
Explanation: "abb", "bab" and "bba" are all correct answers.


Example 2:

Input: A = 4, B = 1
Output: "aabaa"

Note:

1. 0 <= A <= 100
2. 0 <= B <= 100
3. It is guaranteed such an S exists for the given A and B.

## C++

In a country popular for train travel, you have planned some train travelling one year in advance.  The days of the year that you will travel is given as an array days.  Each day is an integer from 1 to 365.

Train tickets are sold in 3 different ways:

• a 1-day pass is sold for costs[0] dollars;
• a 7-day pass is sold for costs[1] dollars;
• a 30-day pass is sold for costs[2] dollars.

The passes allow that many days of consecutive travel.  For example, if we get a 7-day pass on day 2, then we can travel for 7 days: day 2, 3, 4, 5, 6, 7, and 8.

Return the minimum number of dollars you need to travel every day in the given list of days.

Example 1:

Input: days = [1,4,6,7,8,20], costs = [2,7,15]
Output: 11
Explanation:
For example, here is one way to buy passes that lets you travel your travel plan:
On day 1, you bought a 1-day pass for costs[0] = $2, which covered day 1. On day 3, you bought a 7-day pass for costs[1] =$7, which covered days 3, 4, ..., 9.
On day 20, you bought a 1-day pass for costs[0] = $2, which covered day 20. In total you spent$11 and covered all the days of your travel.


Example 2:

Input: days = [1,2,3,4,5,6,7,8,9,10,30,31], costs = [2,7,15]
Output: 17
Explanation:
For example, here is one way to buy passes that lets you travel your travel plan:
On day 1, you bought a 30-day pass for costs[2] = $15 which covered days 1, 2, ..., 30. On day 31, you bought a 1-day pass for costs[0] =$2 which covered day 31.
In total you spent \$17 and covered all the days of your travel.


Note:

1. 1 <= days.length <= 365
2. 1 <= days[i] <= 365
3. days is in strictly increasing order.
4. costs.length == 3
5. 1 <= costs[i] <= 1000

## Solution: DP

dp[i] := min cost to cover the i-th day
dp[0] = 0
dp[i] = min(dp[i – 1] + costs[0], dp[i – 7] + costs[1], dp[i – 30] + costs[2])

## Python

Mission News Theme by Compete Themes.