Thursday, August 13, 2015

Day 119, #239,237,238,240 Sliding Window Maximum, Delete Node in a Linked List, Product of Array Except Self, Different Ways to Add Parentheses

Sliding Window Maximum 
Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.
For example,
Given nums = [1,3,-1,-3,5,3,6,7], and k = 3.
Window position                Max
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7
Therefore, return the max sliding window as [3,3,5,5,6,7].
Note: 
You may assume k is always valid, ie: 1 ≤ k ≤ input array's size for non-empty array.
Follow up:
Could you solve it in linear time?
Hint:
  1. How about using a data structure such as deque (double-ended queue)?
  2. The queue size need not be the same as the window’s size.
  3. Remove redundant elements and the queue should store only elements that need to be considered.
--------------------------------------------------------------------------------
http://articles.leetcode.com/2011/01/sliding-window-maximum.html
compare function的写法跟用法
O(NlgN)
class Cmp{
public:
    bool operator() (pair<int,int> &p1,pair<int,int> &p2) {
        return p1.second < p2.second;
    }  
};

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        if (k == 0) {
            vector<int> rt;
            return rt;
        }
        if (k == 1) return nums;
        vector<int> rt(nums.size() - k + 1);
        priority_queue<pair<int,int>,vector<pair<int,int>>,Cmp> heap; // index, value
        for (int i = 0; i < k - 1; i++) {
            heap.push(make_pair(i,nums[i]));
        }
        
        for (int i = k - 1; i < nums.size(); i++) {
            heap.push(make_pair(i,nums[i]));
            while (heap.top().first < i - k + 1) {
                heap.pop();
            }
            rt[i - k + 1] = heap.top().second;
        }
        
        return rt;
    }
};

O(n)
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int> rt;
        deque<int> que;
        for (int i = 0; i < k - 1; i++) {
            while (!que.empty() && nums[i] >= nums[que.back()]) {
                que.pop_back();
            }
            que.push_back(i);
        }
        
        for (int i = k - 1; i < nums.size(); i++) {
            while (!que.empty() && nums[i] >= nums[que.back()]) {
                que.pop_back();
            }
            if (!que.empty() && que.front() < i - k + 1) {
                que.pop_front();
            }
            que.push_back(i);
            rt.push_back(nums[que.front()]);
        }
        
        return rt;
    }
};

Java
public class Solution {
    
    public int[] maxSlidingWindow(int[] nums, int k) {
        if (nums == null || nums.length == 0 || k <= 0) return new int[0];
        
        int rt[] = new int[nums.length - k + 1];
        Deque<Integer> q = new ArrayDeque<>();
        
        for (int i = 0; i < nums.length; i++) {
            if (!q.isEmpty() && q.getFirst() <= i - k) {
                q.removeFirst();
            }
            
            while (!q.isEmpty() && nums[q.getLast()] < nums[i]) {
                q.removeLast();
            }
            
            q.addLast(i);
            if (i >= k - 1) {
                rt[i - k + 1] = nums[q.getFirst()];
            }
        }
        
        return rt;
    }
}
另一种思路,Deque里的值是递增
class Solution {
    
    public int[] maxSlidingWindow(int[] nums, int k) {
        int n = nums.length;
        if (n == 0) return new int[0];
        
        int[] rt = new int[n - k + 1];
        Deque<Integer> deq = new LinkedList<>();
        
        for (int i = 0; i < n; i++) {
            while (!deq.isEmpty() && deq.peekLast() <= i - k) {
                deq.pollLast();
            }
            
            if (deq.isEmpty() || nums[deq.peekLast()] <= nums[i]) deq.addLast(i);
            else {
                while (!deq.isEmpty() && nums[deq.peekFirst()] <= nums[i]) {
                    deq.pollFirst();
                }
                deq.addFirst(i);
            }
            
            if (i >= k - 1) rt[i - k + 1] = nums[deq.peekLast()];
        }
        
        return rt;
    }
}

Delete Node in a Linked List
Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.
Supposed the linked list is 1 -> 2 -> 3 -> 4 and you are given the third node with value 3, the linked list should become 1 -> 2 -> 4 after calling your function.
-----------------------------------------------

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
        node->val = node->next->val;
        node->next = node->next->next;
    }
};

Product of Array Except Self
Given an array of n integers where n > 1, nums, return an array output such that output[i] is equal to the product of all the elements of nums except nums[i].
Solve it without division and in O(n).
For example, given [1,2,3,4], return [24,12,8,6].
Follow up:
Could you solve it with constant space complexity? (Note: The output array does not count as extra space for the purpose of space complexity analysis.)

-----------------------------------------------------------------
O(n) extra space
class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        vector<int> left(nums.size(),1);
        vector<int> right(nums.size(),1);
        vector<int> rt(nums.size());
        for (int i = 1; i < nums.size(); i++) {
            left[i] = nums[i - 1] * left[i - 1];
        }
        for (int i = nums.size() - 2; i >= 0; i--) {
            right[i] = nums[i + 1] * right[i + 1];
        }
        
        for (int i = 0; i < nums.size(); i++) {
            rt[i] = left[i] * right[i];
        }
        
        return rt;
    }
};

constant space, output array doesn't count as extra space
class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        vector<int> left(nums.size(),1);
        for (int i = 1; i < nums.size(); i++) {
            left[i] = nums[i - 1] * left[i - 1];
        }
        
        int right = 1;
        for (int i = nums.size() - 1; i >= 0; i--) {
            left[i] = right * left[i];
            right *= nums[i];
        }
        
        return left;
    }
};

Different Ways to Add Parentheses
Given a string of numbers and operators, return all possible results from computing all the different possible ways to group numbers and operators. The valid operators are+- and *.

Example 1
Input: "2-1-1".
((2-1)-1) = 0
(2-(1-1)) = 2
Output: [0, 2]

Example 2
Input: "2*3-4*5"
(2*(3-(4*5))) = -34
((2*3)-(4*5)) = -14
((2*(3-4))*5) = -10
(2*((3-4)*5)) = -10
(((2*3)-4)*5) = 10
Output: [-34, -14, -10, -10, 10]
------------------------------------------------------
Catalan number, divide and conquer
以下解法还可做优化
class Solution {
public:
    vector<int> diffWaysToCompute(string s) {
        vector<int> rt;
        
        for (int i = 0; i < s.length(); i++) {
            if (s[i] == '-' || s[i] == '+' || s[i] == '*') {
                vector<int> first = diffWaysToCompute(s.substr(0,i));
                vector<int> second = diffWaysToCompute(s.substr(i + 1));
                for (int j = 0; j < first.size(); j++) {
                    for (int k = 0; k < second.size(); k++) {
                        if (s[i] == '-') {
                            rt.push_back(first[j] - second[k]);
                        }
                        if (s[i] == '+') {
                            rt.push_back(first[j] + second[k]);
                        }
                        if (s[i] == '*') {
                            rt.push_back(first[j] * second[k]);
                        }
                    }
                }
            }
        }
        if (rt.size() == 0) rt.push_back(stoi(s));
        return rt;
    }
};

DP优化
class Solution {
public:
    vector<int> helper(string s, int start, int end,unordered_map<string,vector<int>> &dic) {
        vector<int> rt;
        
        for (int i = start; i <= end; i++) {
            if (s[i] == '-' || s[i] == '+' || s[i] == '*') {
                vector<int> first;
                vector<int> second;
                if (dic.find(s.substr(start,i)) == dic.end()) {
                    first = helper(s,start,i - 1,dic);
                }else first = dic[s.substr(start,i)];
                
                if (dic.find(s.substr(i + 1)) == dic.end()) {
                    second = helper(s,i + 1,end,dic);
                }else second = dic[s.substr(i + 1)];
                
                for (int j = 0; j < first.size(); j++) {
                    for (int k = 0; k < second.size(); k++) {
                        if (s[i] == '-') {
                            rt.push_back(first[j] - second[k]);
                        }
                        if (s[i] == '+') {
                            rt.push_back(first[j] + second[k]);
                        }
                        if (s[i] == '*') {
                            rt.push_back(first[j] * second[k]);
                        }
                    }
                }
            }
        }
        if (rt.size() == 0) rt.push_back(stoi(s.substr(start,end - start + 1)));
        dic[s] = rt;
        return rt;
    }
    
    vector<int> diffWaysToCompute(string input) {
        unordered_map<string,vector<int>> dic;
        return helper(input,0,input.length() - 1,dic);
    }
};

No comments:

Post a Comment