2019年11月11日 星期一

Graph Valid Tree


Graph Valid Tree

  • Lintcode : 178 / Leetcode : 261
  • Level : Medium

Problem

Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), write a function to check whether these edges make up a valid tree.

Example
Example 1:

Input: n = 5 edges = [[0, 1], [0, 2], [0, 3], [1, 4]]
Output: true.
Example 2:

Input: n = 5 edges = [[0, 1], [1, 2], [2, 3], [1, 3], [1, 4]]
Output: false.
Notice
You can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges.

Concept & Algorithm

Time Complexity & Space Complexity

time : O(n)
space: O(n)

Answer

class Solution {
public:
    bool validTree(int n, vector<vector<int>> &edges) {
        // 判斷是否為tree 
        /*
            1. cycle
            2. edges = nodes - 1
        */
        map<int, unordered_set<int>> g;
        unordered_set<int> nodes;
        queue<int> q;
        // 因為不確定哪個會是parent
        // ex: 不一定是 [[0, 1]],可能是[[1, 0]]
        for (auto it : edges) {
            g[it[0]].insert(it[1]);
            g[it[1]].insert(it[0]);
        }
        q.push(0);
        nodes.insert(0);
        while (!q.empty()) {
            int node = q.front(); q.pop();
            for (auto a : g[node]) {
                // 有重複代表有cycle
                if (nodes.find(a) != nodes.end()) return false;
                q.push(a);
                nodes.insert(a);
                g[a].erase(node);
            }
        }
        // 避免 n 很多,但是沒有全部都拿來建構樹
        // ex: n = 3, edges = [[0, 1]]
        return nodes.size() == n;
    }
};
tags: BFS
​

Six Degrees


Six Degrees

  • Lintcode : 531 / Leetcode :
  • Level : Medium

Problem

Six degrees of separation is the theory that everyone and everything is six or fewer steps away, by way of introduction, from any other person in the world, so that a chain of "a friend of a friend" statements can be made to connect any two people in a maximum of six steps.

Given a friendship relations, find the degrees of two people, return -1 if they can not been connected by friends of friends.

Example
Example1

Input: {1,2,3#2,1,4#3,1,4#4,2,3} and s = 1, t = 4 
Output: 2
Explanation:
    1------2-----4
     \          /
      \        /
       \--3--/
Example2

Input: {1#2,4#3,4#4,2,3} and s = 1, t = 4
Output: -1
Explanation:
    1      2-----4
                 /
               /
              3

Concept & Algorithm

Time Complexity & Space Complexity

time : O(nodes * avg neighbors)
space: O(nodes)

Answer

/**
 * Definition for undirected graph.
 * struct UndirectedGraphNode {
 *     int label;
 *     vector<UndirectedGraphNode *> neighbors;
 *     UndirectedGraphNode(int x) : label(x) {};
 * };
 */

class Solution {
public:
    int sixDegrees(vector<UndirectedGraphNode*> graph, UndirectedGraphNode* s, UndirectedGraphNode* t) {
        map<UndirectedGraphNode*, int> degree;
        queue<UndirectedGraphNode*> q;
        q.push(s);
        degree[s] = 0;
        while (!q.empty()) {
            UndirectedGraphNode* n = q.front(); q.pop();
            if (n == t) return degree[t];
            for (auto j : n -> neighbors) {
                if (degree[j] != 0 && degree[j] <= degree[n] + 1) continue;
                degree[j] = degree[n] + 1;
                q.push(j);
            }
        }
        return -1;
    }
};
tags: BFS
​

Zombie in Matrix


Zombie in Matrix

  • Lintcode : 598 / Leetcode :
  • Level : Medium

Problem

Given a 2D grid, each cell is either a wall 2, a zombie 1 or people 0 (the number zero, one, two).Zombies can turn the nearest people(up/down/left/right) into zombies every day, but can not through wall. How long will it take to turn all people into zombies? Return -1 if can not turn all people into zombies.

Example
Example 1:

Input:
[[0,1,2,0,0],
 [1,0,0,2,1],
 [0,1,0,0,0]]
Output:
2
Example 2:

Input:
[[0,0,0],
 [0,0,0],
 [0,0,1]]
Output:
4

Concept & Algorithm

Time Complexity & Space Complexity

time : O(m n)
space: O(m
n) 最壞

Answer

class Solution {
public:
    int zombie(vector<vector<int>> &grid) {
        if (grid.size() == 0 || grid[0].size() == 0) return 0;
        queue<vector<int>> q;
        for (int i = 0; i < grid.size(); i++) {
            for (int j = 0; j < grid[0].size(); j++) {
                if (grid[i][j] == 1) q.push({i, j});
            }
        }
        int days = -1;
        while (!q.empty()) {
            int s = q.size();
            days += 1;
            for (int i = 0; i < s; i++) {
                vector<int> axis = q.front(); q.pop();
                for (auto d : dir) {
                    int x = d[0] + axis[0];
                    int y = d[1] + axis[1];
                    if (!isValid(grid, x, y)) continue;
                    q.push({x, y});
                    grid[x][y] = 1;
                }
            }
        }
        for (int i = 0; i < grid.size(); i++) {
            for (int j = 0; j < grid[0].size(); j++) {
                if (grid[i][j] == 0) return -1;
            }
        }
        return days;
    }
    vector<vector<int>> dir = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    bool isValid (vector<vector<int>> &grid, int x, int y) {
        if (x < 0 || y < 0 || x >= grid.size() || y >= grid[0].size() || grid[x][y] != 0)
            return false;
        return true;
    }
};
tags: BFS
​

Search Graph Nodes


Search Graph Nodes

  • Lintcode : 618 / Leetcode :
  • Level : Medium

Problem

Given a undirected graph, a node and a target, return the nearest node to given node which value of it is target, return NULL if you can't find.

There is a mapping store the nodes' values in the given parameters.

Example
Example 1:

Input:
{1,2,3,4#2,1,3#3,1,2#4,1,5#5,4}
[3,4,5,50,50]
1
50
Output:
4
Explanation:
2------3  5
 \     |  | 
  \    |  |
   \   |  |
    \  |  |
      1 --4
Give a node 1, target is 50

there a hash named values which is [3,4,10,50,50], represent:
Value of node 1 is 3
Value of node 2 is 4
Value of node 3 is 10
Value of node 4 is 50
Value of node 5 is 50

Return node 4
Example 2:

Input:
{1,2#2,1}
[0,1]
1
1
Output:
2
Notice
It's guaranteed there is only one available solution

Concept & Algorithm

Time Complexity & Space Complexity

time : O(nodes * avg edges)
space: O(n)

Answer

/**
 * Definition for Undirected graph.
 * struct UndirectedGraphNode {
 *     int label;
 *     vector<UndirectedGraphNode *> neighbors;
 *     UndirectedGraphNode(int x) : label(x) {};
 * };
 */

class Solution {
public:
     UndirectedGraphNode* searchNode(vector<UndirectedGraphNode*>& graph,
                                    map<UndirectedGraphNode*, int>& values,
                                    UndirectedGraphNode* node,
                                    int target) {
                                        if (node == nullptr) return nullptr;
                                        queue<UndirectedGraphNode*> q;
                                        q.push(node);
                                        set<UndirectedGraphNode*> repeat;
                                        while (!q.empty()) {
                                            UndirectedGraphNode* n = q.front(); q.pop();
                                                if (values[n] == target) return n;
                                                for (auto j : n -> neighbors) {
                                                    if (repeat.find(j) != repeat.end()) continue;
                                                    q.push(j);
                                                    repeat.insert(j);
                                                }
                                        }
                                        return nullptr;
    }
};
tags: BFS
​

Remove Substrings


Remove Substrings

  • Lintcode : 624 / Leetcode :
  • Level : Medium

Problem

Given a string s and a set of n substrings. You are supposed to remove every instance of those n substrings from s so that s is of the minimum length and output this minimum length.

Example
Example 1:

Input:
"ccdaabcdbb"
["ab","cd"]
Output:
2
Explanation: 
ccdaabcdbb -> ccdacdbb -> cabb -> cb (length = 2)
Example 2:

Input:
"abcabd"
["ab","abcd"]
Output:
0
Explanation: 
abcabd -> abcd -> "" (length = 0)

Concept & Algorithm

Time Complexity & Space Complexity

time : O()
space: O()

Answer

class Solution {
public:
    int minLength(string &s, unordered_set<string> &dict) {
        queue<string> q;
        unordered_set<string> repeat;
        q.push(s);
        repeat.insert(s);
        int minLen = s.length();
        while (!q.empty()) {
            string str = q.front(); q.pop();
            for (auto d : dict) {
                int index = str.find(d);
                while (index != -1) {
                    int len = d.size();
                    string newStr = str.substr(0, index) + str.substr(index + len, str.size() - len - index);
                    if (repeat.find(newStr) == repeat.end()) {
                        minLen = min(minLen, (int)newStr.size());
                        q.push(newStr);
                        repeat.insert(newStr);
                    }
                    // 嘗試不同組合
                    index = str.find(d, index + 1);
                }
            }
        }
        return minLen;
    }
};

/*
不同的組合可以有不同的答案,因此不能照順序消除
"abcabd"
["ab","abcd"]
Output
2
Expected
0
*/
tags: BFS
​

2019年11月10日 星期日

The Maze II


The Maze II

  • Lintcode : 788 / Leetcode : 505
  • Level : Medium

Problem

There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolling up, down, left or right, but it won't stop rolling until hitting a wall. When the ball stops, it could choose the next direction.

Given the ball's start position, the destination and the maze, find the shortest distance for the ball to stop at the destination. The distance is defined by the number of empty spaces traveled by the ball from the start position (excluded) to the destination (included). If the ball cannot stop at the destination, return -1.

The maze is represented by a binary 2D array. 1 means the wall and 0 means the empty space. You may assume that the borders of the maze are all walls. The start and destination coordinates are represented by row and column indexes.

Example
Example 1:
    Input:  
    (rowStart, colStart) = (0,4)
    (rowDest, colDest)= (4,4)
    0 0 1 0 0
    0 0 0 0 0
    0 0 0 1 0
    1 1 0 1 1
    0 0 0 0 0

    Output:  12

    Explanation:
    (0,4)->(0,3)->(1,3)->(1,2)->(1,1)->(1,0)->(2,0)->(2,1)->(2,2)->(3,2)->(4,2)->(4,3)->(4,4)

Example 2:
    Input:
    (rowStart, colStart) = (0,4)
    (rowDest, colDest)= (0,0)
    0 0 1 0 0
    0 0 0 0 0
    0 0 0 1 0
    1 1 0 1 1
    0 0 0 0 0

    Output:  6

    Explanation:
    (0,4)->(0,3)->(1,3)->(1,2)->(1,1)->(1,0)->(0,0)

Notice
1.There is only one ball and one destination in the maze.
2.Both the ball and the destination exist on an empty space, and they will not be at the same position initially.
3.The given maze does not contain border (like the red rectangle in the example pictures), but you could assume the border of the maze are all walls.
4.The maze contains at least 2 empty spaces, and both the width and height of the maze won't exceed 100.

Concept & Algorithm

Time Complexity & Space Complexity

time : O(avg steps can roll avg stop point)
space: O(m
n)

Answer

class Solution {
public:
    int shortestDistance(vector<vector<int>> &maze, vector<int> &start, vector<int> &destination) {
        int m = maze.size(), n = maze[0].size();
        vector<vector<int>> step(m, vector<int>(n));
        queue<vector<int>> q;
        q.push(start);
        step[start[0]][start[1]] = 0;
        while (!q.empty()) {
            vector<int> h = q.front(); q.pop();
            if (h[0] == destination[0] && h[1] == destination[1]) return step[h[0]][h[1]];
            for (auto d : dir) {
                vector<int> stop = rolling(maze, h, d);
                int len = step[h[0]][h[1]] + abs((stop[0] - h[0]) + (stop[1] - h[1])); 
                if (step[stop[0]][stop[1]] != 0 && len >= step[stop[0]][stop[1]]) continue;

                step[stop[0]][stop[1]] = len;
                q.push(stop);
            }    
        }
        return -1;
    }
    vector<vector<int>> dir = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
    vector<int> rolling(vector<vector<int>> &maze, vector<int> h, vector<int> d) {
        int x = h[0], y = h[1];
        while (x >= 0 && y >= 0 && x < maze.size() && y < maze[0].size() && !maze[x][y]) {
            x += d[0];
            y += d[1];
        }
        x -= d[0];
        y -= d[1];
        return {x, y};
    }
};
tags: BFS
​

The Maze


The Maze

  • Lintcode : 787 / Leetcode : 490
  • Level : Medium

Problem

There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolling up, down, left or right, but it won't stop rolling until hitting a wall. When the ball stops, it could choose the next direction.

Given the ball's start position, the destination and the maze, determine whether the ball could stop at the destination.

The maze is represented by a binary 2D array. 1 means the wall and 0 means the empty space. You may assume that the borders of the maze are all walls. The start and destination coordinates are represented by row and column indexes.

Example
Example 1:

Input:
map = 
[
 [0,0,1,0,0],
 [0,0,0,0,0],
 [0,0,0,1,0],
 [1,1,0,1,1],
 [0,0,0,0,0]
]
start = [0,4]
end = [3,2]
Output:
false
Example 2:

Input:
map = 
[[0,0,1,0,0],
 [0,0,0,0,0],
 [0,0,0,1,0],
 [1,1,0,1,1],
 [0,0,0,0,0]
]
start = [0,4]
end = [4,4]
Output:
true
Notice
1.There is only one ball and one destination in the maze.
2.Both the ball and the destination exist on an empty space, and they will not be at the same position initially.
3.The given maze does not contain border (like the red rectangle in the example pictures), but you could assume the border of the maze are all walls.
5.The maze contains at least 2 empty spaces, and both the width and height of the maze won't exceed 100.

Concept & Algorithm

Time Complexity & Space Complexity

time : O(avg steps can roll avg stop point)
space: O(m
n)

Answer

class Solution {
public:
    bool hasPath(vector<vector<int>> &maze, vector<int> &start, vector<int> &destination) {
        int m = maze.size(), n = maze[0].size();
        queue<vector<int>> q;
        vector<vector<bool>> isVisited(m, vector<bool>(n, false));
        q.push(start);
        isVisited[start[0]][start[1]] = true;
        while (!q.empty()) {
            vector<int> h = q.front(); q.pop();
            if (h[0] == destination[0] && h[1] == destination[1]) return true;
            for (auto d : dir) {
                vector<int> stop = rolling(maze, d, h);
                if (isVisited[stop[0]][stop[1]]) continue;
                q.push(stop);
                isVisited[stop[0]][stop[1]] = true;
            }
        }
        return false;
    }
    vector<vector<int>> dir = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
    vector<int> rolling(vector<vector<int>> &maze, vector<int> d, vector<int> h) {
        int x = h[0], y = h[1];
        while (x >= 0 && y >= 0 && x < maze.size() && y < maze[0].size() && !maze[x][y]) {
            x += d[0];
            y += d[1];
        }
        x -= d[0];
        y -= d[1];
        return {x, y};
    }
};
tags: BFS
​

Convert Binary Tree to Linked Lists by Depth


Convert Binary Tree to Linked Lists by Depth

  • Lintcode : 242 / Leetcode :
  • Level : Easy

Problem

Given a binary tree, design an algorithm which creates a linked list of all the nodes at each depth (e.g., if you have a tree with depth D, you'll have D linked lists).

Example
Example 1:

Input: {1,2,3,4}
Output: [1->null,2->3->null,4->null]
Explanation: 
        1
       / \
      2   3
     /
    4
Example 2:

Input: {1,#,2,3}
Output: [1->null,2->null,3->null]
Explanation: 
    1
     \
      2
     /
    3

Concept & Algorithm

Time Complexity & Space Complexity

time : O(n)
space: O(n)

Answer

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    vector<ListNode*> binaryTreeToLists(TreeNode* root) {
        // corner case 
        if (root == nullptr) return vector<ListNode*>();

        queue<TreeNode*> q;
        q.push(root);
        vector<ListNode*> ans;
        while (!q.empty()) {
            int s = q.size(); // level order
            ListNode* head = new ListNode(0);
            ListNode* dummy = head;
            for (int i = 0; i < s; i++) {
                TreeNode* node = q.front(); q.pop();
                head -> next = new ListNode(node -> val);
                if (node -> left) q.push(node -> left);
                if (node -> right) q.push(node -> right);
                head = head -> next;
            }
            ans.push_back(dummy -> next);
        }
        return ans;
    }
};
tags: BFS
​

2019年11月9日 星期六

Median of K Sorted Arrays


Median of K Sorted Arrays

  • Lintcode : 931
  • Level : Hard

Problem

There are k sorted arrays nums. Find the median of the given k sorted arrays.

Example
Example 1:

Input:
[[1],[2],[3]]
Output:
2.00
Example 2:

Input:
[[1,1,2],[2,4,8],[3,7,10,20]]
Output:
3.50
Notice
The length of the given arrays may not equal to each other.
The elements of the given arrays are all positive number.
Return 0 if there are no elements in the array.
In order to ensure time complexity, the program will be executed repeatedly.

Concept & Algorithm

Time Complexity & Space Complexity

time : O(log(maximum - minimum) n logm)
(n = elements in nums, m = avg elements in n)
space: O(1)

Answer

class Solution {
public:
    double findMedian(vector<vector<int>> &nums) {
        if (nums.size() == 0) return 0;
        int n = 0;
        for (auto i : nums) {
            if (i.empty()) continue;
            n += i.size();
        }
        if (n == 0) return 0;
        if (n & 1) {   
            return findKth(nums, n / 2 + 1);    
        }else {
            return (findKth(nums, n / 2) + findKth(nums, n / 2 + 1)) / 2.0;
        }
    }

private:
    double findKth (vector<vector<int>> &nums, int k) {
        int lb = INT_MAX, ub = INT_MIN;
        for (auto i : nums){
            if (i.empty()) continue;
            lb = min(lb, i[0]);
            ub = max(ub, i.back());
        }
        int start = lb, end = ub;
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (count(nums, mid) >= k) {
                end = mid;
            }else if (count(nums, mid) < k) {
                start = mid; ;
            }
        }
        if (count(nums, start) == k) return start;
        return end;
    }
    int count(vector<vector<int>> &nums, int key) {
        int count = 0;
        for (auto i : nums) {
            if (i.empty()) continue;
            count += countLessAndEqual(i, key);
        }
        return count;
    }
    int countLessAndEqual(vector<int> &n, int key) {
        int l = 0, r = n.size() - 1; 
        while (l + 1 < r) {
            int mid = l + (r - l) / 2;
            if (n[mid] <= key) {
                l = mid;
            }else {
                r = mid;
            }
        }
        if (n[l] > key) return l;
        if (n[r] > key) return r;
        return n.size();
    }
};
tags: Binary Search
​

Median of two Sorted Arrays


Median of two Sorted Arrays

  • Lintcode : 65 / Leetcode : 4
  • Level : Hard

Problem

There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays.

Example
Example 1

Input:
A = [1,2,3,4,5,6]
B = [2,3,4,5]
Output: 3.5
Example 2

Input:
A = [1,2,3]
B = [4,5]
Output: 3
Challenge
The overall run time complexity should be O(log (m+n)).

Clarification
The definition of the median:

The median here is equivalent to the median in the mathematical definition.

The median is the middle of the sorted array.

If there are n numbers in the array and n is an odd number, the median is A[(n-1)/2]A[(n−1)/2].

If there are n numbers in the array and n is even, the median is (A[n / 2] + A[n / 2 + 1]) / 2.

For example, the median of the array A=[1,2,3] is 2, and the median of the array A=[1,19] is 10.

Concept & Algorithm

Time Complexity & Space Complexity

time : O(log(A.size() + B.size())
space: O(1)

Answer

class Solution {
public:
    double findMedianSortedArrays(vector<int> &A, vector<int> &B) {
        int len = A.size() + B.size();
        if (len == 0) return 0;
        double ret = 0;
        if (len & 1) {
            ret = finKth(A, B, 0, 0, len / 2 + 1);
        }else {
            ret = (finKth(A, B, 0, 0, len / 2) + finKth(A, B, 0, 0, len / 2 + 1)) / 2.0;
        }
        return ret;
    }
    int finKth (vector<int> &A, vector<int> &B, int a, int b, int k) {
        if (a >= A.size()) return B[b + k - 1];
        if (b >= B.size()) return A[a + k - 1];
        if (k == 1) return min(A[a], B[b]);
        int keyA = a + k / 2 - 1 >= A.size() ? INT_MAX : A[a + k / 2 - 1];
        int keyB = b + k / 2 - 1 >= B.size() ? INT_MAX : B[b + k / 2 - 1];
        if (keyA < keyB) {
            return finKth(A, B, a + k / 2, b, k - k / 2);
        }else {
            return finKth(A, B, a, b + k / 2, k - k / 2);
        }
    }
};
tags: other
​

Last Position of Target

Last Position of Target Lintcode : 458 / Leetcode : 34 Level : Easy Problem Find the last position of a target number in a sorted ...