Sunday, June 14, 2015

Day 107, ##, Minimum Size Subarray Sum, Course Schedule II

Minimum Size Subarray Sum
Given an array of n positive integers and a positive integer s, find the minimal length of a subarray of which the sum ≥ s. If there isn't one, return 0 instead.
For example, given the array [2,3,1,2,4,3] and s = 7,
the subarray [4,3] has the minimal length under the problem constraint.
More practice:
If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n).
-------------------------------------------------------
Sliding window, O(n)

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        if (nums.size() == 0) return 0;
        int minLen = INT_MAX;
        int right = 0, left = 0;
        
        int sum = nums[right];
        while (right < nums.size()) {
            if (sum < s) {
                right++;
                sum += nums[right];
            }else {
                minLen = min(right - left + 1, minLen);
                sum -= nums[left];
                left++;
            }
        }
        
        if (minLen == INT_MAX) return 0;
        return minLen;
    }
};
O(NlogN),
sums[i]计算了nums[0 : i + 1]的连续值,所以sums内的值是递增,由此可以用binary search
所求的最短subarray就是计算 sums[i] + s >= sums[j], j取[1: ]
注意各variable的取值
binary()返回的值可能会等于 sums.size(),


class Solution {
public:
    int binary(int s, vector<int> &sums, int left) {
        int right = sums.size() - 1;
        int minLen = INT_MAX;
        int sum = 0;
        
        while (left <= right) {
            int mid = left + (right - left) / 2; 
            if (sums[mid] >= s) {
                right = mid - 1;
            }else {
                left = mid + 1;
            }
        }
        
        return left;
    }

    int minSubArrayLen(int s, vector<int>& nums) {
        if (nums.size() == 0) return 0;
        int minLen = INT_MAX;
        
        vector<int> sums(nums.size() + 1,0);
        for (int i = 1; i <= nums.size(); i++) {
            sums[i] = sums[i - 1] + nums[i - 1];
        }
        
        for (int i = 0; i < nums.size(); i++) {
            int end = binary(s + sums[i - 1],sums,i);
            if (end == sums.size()) break;
            minLen = min(end - i + 1, minLen);
        }
        
        if (minLen == INT_MAX) return 0;
        return minLen;
    }
};

Java O(n)版本
class Solution {
    public int minSubArrayLen(int s, int[] nums) {
        int n = nums.length;
        int start = 0;
        int minLen = n + 1;
        int sum = 0;
        
        for (int i = 0; i < n; i++) {
            sum += nums[i];
            
            while (sum >= s) {
                minLen = Math.min(minLen, i - start + 1);
                sum -= nums[start];
                start++;
            }
        }
        
        return minLen > n ? 0 : minLen;
    }
}
Course Schedule II
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, return the ordering of courses you should take to finish all courses.
There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array.
For example:
2, [[1,0]]
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]
4, [[1,0],[2,0],[3,1],[3,2]]
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].
Note:
The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
Hints:
  1. This problem is equivalent to finding the topological order in a directed graph. If a cycle exists, no topological ordering exists and therefore it will be impossible to take all courses.
  2. Topological Sort via DFS - A great video tutorial (21 minutes) on Coursera explaining the basic concepts of Topological Sort.
  3. Topological sort could also be done via BFS.
-----------------------------------------------------
topological sort, 考虑cycle问题
DFS
class Solution {
public:
    bool dfs(vector<vector<int>> &edges,int course,vector<int> &visit,vector<int> &path) {
        if (visit[course] == -1) return false;
        if (visit[course] == 1) return true;
        visit[course] = -1;
        
        for (int i = 0; i < edges[course].size(); i++) {
            if (!dfs(edges,edges[course][i],visit,path)) return false;
        }
        path.push_back(course);
        visit[course] = 1;
        return true;
    }

    vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) {
        vector<vector<int>> edges(numCourses,vector<int>());
        vector<int> path;
        vector<int> visit(numCourses,0);    
        
        for (int i = 0; i < prerequisites.size(); i++) {
            edges[prerequisites[i].second].push_back(prerequisites[i].first);
        }
        for (int i = 0; i < numCourses; i++) {
            if (!dfs(edges,i,visit,path)) {
                vector<int> rt;
                return rt;
            }
        }
        reverse(path.begin(),path.end());
        return path;
    }
};
BFS
ref: https://en.wikipedia.org/wiki/Topological_sorting#Algorithms
class Solution {
public:
    vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) {
        vector<vector<int> > edges(numCourses);
        vector<int> order;
        vector<int> inDegree(numCourses,0);
        queue<int> que;
        
        for (int i = 0; i < prerequisites.size(); i++) {
            edges[prerequisites[i].second].push_back(prerequisites[i].first);
            inDegree[prerequisites[i].first]++;
        }
        
        for (int i = 0; i < numCourses; i++) {
            if (inDegree[i] == 0) {
                que.push(i);
            }
        }
        
        while (!que.empty()) {
            int current = que.front();
            que.pop();
            order.push_back(current)
            ;
            for (int i = 0; i < edges[current].size(); i++) {
                int neighbor = edges[current][i];
                inDegree[neighbor]--;
                if (inDegree[neighbor] == 0) {
                    que.push(neighbor);
                }
            }
        }
        
        for (int i = 0; i < numCourses; i++) {
            if (inDegree[i] != 0) {
                order = vector<int>();
                return order;
            }
        }
        
        return order;
    }
};

No comments:

Post a Comment