Wednesday, May 13, 2015

LeetCode [209] Minimum Size Subarray Sum

 209. Minimum Size Subarray Sum

Medium

Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn't one, return 0 instead.

Example: 

Input: s = 7, nums = [2,3,1,2,4,3]
Output: 2
Explanation: the subarray [4,3] has the minimal length under the problem constraint.
Follow up:
If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n). 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
//C++: method1 4ms
class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int n = nums.size(), l = 0, r = 0, sum = 0, ret = INT_MAX;
        bool found = false;
        while(r<n){
            sum += nums[r++];
            while(sum-nums[l]>=s){
                sum -= nums[l++];
            }
            if(sum>=s){
                ret = min(ret, r-l);
                found = true;
            }
        }
        return found?ret:0;
    }
};

LeetCode [208] Implement Trie (Prefix Tree)

 208. Implement Trie (Prefix Tree)

Medium

Trie (we pronounce "try") or prefix tree is a tree data structure used to retrieve a key in a strings dataset. There are various applications of this very efficient data structure, such as autocomplete and spellchecker.

Implement the Trie class:

  • Trie() initializes the trie object.
  • void insert(String word) inserts the string word to the trie.
  • boolean search(String word) returns true if the string word is in the trie (i.e., was inserted before), and false otherwise.
  • boolean startsWith(String prefix) returns true if there is a previously inserted string word that has the prefix prefix, and false otherwise.

 

Example 1:

Input
["Trie", "insert", "search", "search", "startsWith", "insert", "search"]
[[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]]
Output
[null, null, true, false, true, null, true]

Explanation
Trie trie = new Trie();
trie.insert("apple");
trie.search("apple");   // return True
trie.search("app");     // return False
trie.startsWith("app"); // return True
trie.insert("app");
trie.search("app");     // return True

 

Constraints:

  • 1 <= word.length, prefix.length <= 2000
  • word and prefix consist of lowercase English letters.
  • At most 3 * 104 calls will be made to insertsearch, and startsWith.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
class Trie {
    class TrieNode{
        boolean isEnd;
        TrieNode[] children;
        TrieNode(){
            isEnd = false;
            children = new TrieNode[26];
        }
    }
    TrieNode root;

    /** Initialize your data structure here. */
    public Trie() {
        root = new TrieNode();
    }
    
    /** Inserts a word into the trie. */
    public void insert(String word) {
        TrieNode p = root;
        for(char c : word.toCharArray()){
            if(p.children[c-'a']==null){
                p.children[c-'a'] = new TrieNode();
            }
            p = p.children[c-'a'] ;
        }
        p.isEnd = true;
    }
    
    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        TrieNode p = root;
        for(char c : word.toCharArray()){
            if(p.children[c-'a']==null){
                return false;
            }
            p = p.children[c-'a'] ;
        }
        return p.isEnd == true;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        TrieNode p = root;
        for(char c : prefix.toCharArray()){
            if(p.children[c-'a']==null){
                return false;
            }
            p = p.children[c-'a'] ;
        }
        return true;
    }
}

/**
 * Your Trie object will be instantiated and called as such:
 * Trie obj = new Trie();
 * obj.insert(word);
 * boolean param_2 = obj.search(word);
 * boolean param_3 = obj.startsWith(prefix);
 */

LeetCode [210] Course Schedule II

 210. Course Schedule II

Medium

There are a total of n courses you have to take labelled from 0 to n - 1.

Some courses may have prerequisites, for example, if prerequisites[i] = [ai, bi] this means you must take the course bi before the course ai.

Given the total number of courses numCourses and a list of the prerequisite pairs, return the ordering of courses you should take to finish all courses.

If there are many valid answers, return any of them. If it is impossible to finish all courses, return an empty array.

 

Example 1:

Input: numCourses = 2, prerequisites = [[1,0]]
Output: [0,1]
Explanation: There are a total of 2 courses to take. To take course 1 you should have finished course 0. So the correct course order is [0,1].

Example 2:

Input: numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]]
Output: [0,2,1,3]
Explanation: There are a total of 4 courses to take. To take course 3 you should have finished both courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0.
So one correct course order is [0,1,2,3]. Another correct ordering is [0,2,1,3].

Example 3:

Input: numCourses = 1, prerequisites = []
Output: [0]

 

Constraints:

  • 1 <= numCourses <= 2000
  • 0 <= prerequisites.length <= numCourses * (numCourses - 1)
  • prerequisites[i].length == 2
  • 0 <= ai, bi < numCourses
  • ai != bi
  • All the pairs [ai, bi] are distinct.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//C++: method1 740ms label the courses along the recursion
class Solution {
public:
    vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) {
        vector<int> label(numCourses), ret;
        bool visited[2000] = {false};
        int cur_label = numCourses;
        for(int i=0; i<numCourses; ++i){
            if(!visited[i]) dfs(i, prerequisites, visited, label, cur_label, ret);
        }
        for(auto p:prerequisites){
            if(label[p.first]<label[p.second]){
                return vector<int>();
            }
        }
        reverse(ret.begin(), ret.end());
        return ret;
    }
    
    void dfs(int course, vector<pair<int, int>>& prerequisites, bool *visited, vector<int> &label, int &cur_label, vector<int> &ret){
        visited[course] = true;
        for(auto p:prerequisites){
            if(course==p.second && !visited[p.first]){
                dfs(p.first, prerequisites, visited, label, cur_label, ret);
            }
        }
        label[course] = --cur_label;
        ret.push_back(course);
    }    
};

//C++: method2 524ms standard dfs method using a stack
#define NC 2000
class Solution {
public:
    vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) {
        bool preqs[NC][NC] = {false};
        for(auto p:prerequisites) preqs[p.second][p.first] = true;
        bool visited[NC] = {false};
        bool path[NC] = {false};

        stack<int> stk;
        vector<int> ret;
        for(int i=0; i<numCourses; ++i){
            if(!visited[i]){
                path[i] = true;
                if(hasCycle(numCourses, i, stk, preqs, visited, path)) return ret;
                path[i] = false;
            }
        }

        while(!stk.empty()){
            ret.push_back(stk.top());
            stk.pop();
        }
        return ret;

    }
    
    bool hasCycle(int N, int node, stack<int> &stk, bool preqs[][NC], bool *visited, bool *path){
        visited[node] = true;
        for(int i=0; i<N; ++i){
            if(preqs[node][i]){
                if(path[i]) return true;
                path[i] = true;
                if(!visited[i]) if(hasCycle(N, i, stk, preqs, visited, path)) return true;
                path[i] = false;
            }
        }
        stk.push(node);
        return false;
    }
};

//C++: method3 620ms  dfs method without a stack
class Solution {
public:
    vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) {
        vector<int> order;
        bool visited[numCourses];
        memset(visited, false, numCourses*sizeof(bool));
        bool path[numCourses];
        memset(path, false, numCourses*sizeof(bool));

        for(int i=0; i<numCourses; ++i){
            path[i] = true;
            if(!visited[i] && hasCycle(numCourses, prerequisites, i, visited, path, order)){
                order.clear();
                return order;
            }
            path[i] = false;
        }
        reverse(order.begin(), order.end());
        return order;
    }
    bool hasCycle(int numCourses, vector<pair<int, int>>& prerequisites, int curNode, bool *visited, bool *path, vector<int> &order){
        visited[curNode] = true;
        for(auto p:prerequisites){
            if(p.second==curNode){
                if(path[p.first]) return true;
                if(!visited[p.first]){
                    path[p.first] = true;
                    if(hasCycle(numCourses, prerequisites, p.first, visited, path, order))
                        return true;
                    path[p.first] = false;
                }
            }
        }
        order.push_back(curNode);
        return false;
    }
};

//Java
class Solution {
    Set<Integer> path, visited;
    Map<Integer, Set<Integer>> preqs;
    List<Integer> schedule;
    public int[] findOrder(int numCourses, int[][] prerequisites) {
        path = new HashSet<>();
        visited = new HashSet<>();
        preqs = new HashMap<>();
        schedule = new ArrayList<>();
        for(int[] p : prerequisites){
            preqs.computeIfAbsent(p[0], k -> new HashSet<Integer>()).add(p[1]);
        }

        for(int c = 0; c<numCourses; ++c){
            path.add(c);
            if(!visited.contains(c) && hasCycle(c))
                return new int[0];
            path.remove(c);
        }

        int[] ret = new int[schedule.size()];
        for(int i=0; i<schedule.size(); ++i) ret[i] = schedule.get(i);
        return ret;
    }

    boolean hasCycle(int course){
        visited.add(course);
        if(preqs.containsKey(course)){
            for(int p : preqs.get(course)){
                if(path.contains(p)) return true;
                path.add(p);
                if(!visited.contains(p) && hasCycle(p)) return true;
                path.remove(p);
            }
        }
        schedule.add(course);
        return false;
    }
}

Tuesday, May 12, 2015

LeetCode [207] Course Schedule

207. Course Schedule
Medium
There are a total of n courses you have to take, labeled from 0 to n-1.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?
Example 1:
Input: 2, [[1,0]] 
Output: true
Explanation: There are a total of 2 courses to take. 
             To take course 1 you should have finished course 0. So it is possible.
Example 2:
Input: 2, [[1,0],[0,1]]
Output: false
Explanation: There are a total of 2 courses to take. 
             To take course 1 you should have finished course 0, and to take course 0 you should
             also have finished course 1. So it is impossible.
Note:
  1. The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
  2. You may assume that there are no duplicate edges in the input prerequisites.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution {
public:
    void dfs(int index, int & current_label, vector<pair<int, int>>& prerequisites, int *visited, int *label, int numCourses){
        visited[index] = 1;
        for(vector<pair<int, int>>::iterator it=prerequisites.begin(); it!=prerequisites.end(); it++){
            if(it->first==index){
                if(visited[it->second]==0)
                    dfs(it->second, current_label, prerequisites, visited, label, numCourses);
            }
        }
        label[index] = current_label--;
    }

    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
        int visited[2000] = {0};
        int label[numCourses];
        int current_label = numCourses-1;
        for(int i=0; i<numCourses; ++i) {
            if(visited[i]==0){
                dfs(i, current_label, prerequisites, visited, label, numCourses);
            }
        }
        for(vector<pair<int, int>>::iterator it=prerequisites.begin(); it!=prerequisites.end(); it++){
            if(label[it->first]>label[it->second]) return false;
        }
        return true;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
enum class Color{white, gray, black};

class Solution {
    vector<Color> colors;
public:
    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
        colors.resize(numCourses, Color::white);
        for(int i=0; i<numCourses; ++i){
            if(colors[i]==Color::white){
                if(hasCycle(i, prerequisites)) return false;
            }
        }
        return true;
    }

    bool hasCycle(int course, vector<pair<int, int>>& prerequisites){
        colors[course] = Color::gray;
        for(auto p:prerequisites){
            if(p.second==course){
                if(colors[p.first]==Color::gray) return true;
                if(colors[p.first]==Color::white){
                    if(hasCycle(p.first, prerequisites)) return true;
                }
            }
        }
        colors[course] = Color::black;
        return false;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Solution {
public:
    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
        int current_label = numCourses, i = 0;
        stack<int> stk;
        bool visited[numCourses];
        int labels[numCourses];
        memset(visited, false, numCourses*sizeof(bool));
        
        while(i<numcourses || !stk.empty()){
            if(stk.empty()){
                while(i<numCourses && visited[i]) i++;
                if(i<numCourses) stk.push(i);
            }else{
                int u = stk.top();
                visited[u] = true;
                bool hasChild = false;
                for(auto p:prerequisites){
                    if(p.first==u){
                        int v = p.second;
                        if(!visited[v]){ stk.push(v); hasChild = true;}
                    }
                }
                if(!hasChild){ 
                    labels[u] = current_label--; 
                    stk.pop();
                }
            }
        }
        
        for(auto p:prerequisites){
            int u = p.first, v = p.second;
            if(labels[u]>labels[v]) return false;
        }
        return true;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class Solution {
public:

    bool isSource(int index, vector<pair<int, int>>& prerequisites, int N, int *deletedEdge, int nE){
        int s[N];
        memset(s,0,N*sizeof(int));
        for(int i=0; i<nE; ++i){
            if(deletedEdge[i]==0) s[prerequisites[i].second] = 1;//it->second is not source
        }
        return s[index]==0;
    }

    queue<int> getSources(vector<pair<int, int>>& prerequisites, int N, int *deletedEdge, int nE){
        queue<int> sources;
        int s[N];
        memset(s,0,N*sizeof(int));
        for(int i=0; i<nE; ++i){
            if(deletedEdge[i]==0) s[prerequisites[i].second] = 1;//it->second is not source
        }
        for(int i=0; i<N; ++i){
            if(s[i]==0) sources.push(i);
        }
        return sources;
    }



    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
        int nE = prerequisites.size();
        int deletedEdge[nE];
        memset(deletedEdge,0,nE*sizeof(int));
        queue<int> sources = getSources(prerequisites, numCourses, deletedEdge, nE);
        int delE = 0;
        while(!sources.empty()){
            int n = sources.front();
            sources.pop();
            for(int i=0; i<nE; ++i){
                if(deletedEdge[i]==0 && prerequisites[i].first==n){
                    int m = prerequisites[i].second;
                    deletedEdge[i] = 1;
                    delE++;
                    if(isSource(m, prerequisites, numCourses, deletedEdge, nE)){
                        sources.push(m);
                    }
                }
            }
        }
        return delE==nE;
    }

};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public:
    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
        vector<unordered_set<int>> prs(numCourses);
        for(auto p:prerequisites){
            prs[p.second].insert(p.first);
        }

        unordered_set<int> visited;
        for(int i=0; i<numCourses; i++){
            unordered_set<int> path;
            path.insert(i);
            if(visited.count(i)==0 && hasCycle(numCourses, prs, path, i, visited)) return false;
        }
        return true;
    }
    bool hasCycle(int numCourses, vector<unordered_set<int>> &prs, unordered_set<int> &path, int node, unordered_set<int> &visited){
        visited.insert(node);
        for(int i:prs[node]){
            if(path.count(i)>0) return true;
            path.insert(i);
            if(visited.count(i)==0 && hasCycle(numCourses, prs, path, i, visited)) return true;
            path.erase(i);
        }
        return false;
    }
};

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
    Set<Integer> visited;   
    Set<Integer> path;
    Map<Integer, Set<Integer>> preq;
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        visited = new HashSet<>();
        path = new HashSet<>();
        preq = new HashMap<>();
        for(int[] p : prerequisites){
           preq.computeIfAbsent(p[0], k -> new HashSet<>()).add(p[1]);
        }

        for(int c = 0; c<numCourses; ++c){
            path.add(c);
            if(!visited.contains(c) && hasCycle(c)) return false;
            path.remove(c);
        }        
        return true;
    }

    boolean hasCycle(int course){
        visited.add(course);
        if(!preq.containsKey(course)) return false;
        for(int p : preq.get(course)){
            if(path.contains(p)) return true;
            path.add(p);
            if(hasCycle(p)) return true;
            path.remove(p);
        }
        return false;
    }
}