Leetcode Google Tag

簡(jiǎn)書原創(chuàng)描滔,轉(zhuǎn)載請(qǐng)聯(lián)系作者

// Longest Absolute File Path (Tricky)
// The input string "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext"
// the longest absolute path is "dir/subdir2/subsubdir2/file2.ext", and its length is 32
// 用stack或者vector模擬layers
class Solution {
public:
    vector<string> split(string &s) {
        vector<string> res;
        stringstream ss(s);
        string str;
        while (getline(ss, str)) {
            res.push_back(str);
        }
        return res;
    }
    int lengthLongestPath(string input) {
        int max_len = 0;
        vector<int> level;
        for (string s : split(input)) {
            int cur_level = s.find_last_of('\t') + 1; // number of '\t's
            int cur_len = s.size() - cur_level + 1;
            if (cur_level != 0)
                cur_len += level[cur_level - 1];
            if (cur_level + 1 > level.size())
                level.push_back(cur_len);
            else
                level[cur_level] = cur_len;
            if (s.find('.') != -1)
                max_len = max(max_len, level[cur_level] - 1);
        }
        return max_len;
    }
};
// K Empty Slots (Tricky)
// flowers[i] = x means that the unique flower that blooms at day i will be at position x, where i and x will be in the range from 1 to N.
// Also given an integer k, you need to output in which day there exists two flowers in the status of blooming, and also the number of flowers between them is k and these flowers are not blooming.
// Solution 1: Use C++ ordered set O(nlogn)
// Search, removal, and insertion operations have logarithmic complexity. 
// Sets are usually implemented as red-black trees
// Insert the position into an ordered set day by day, then check the inserted flower’s neighbor to the left and right to see if they are k+1 positions-away from each other.
class Solution {
public:
    int kEmptySlots(vector<int>& flowers, int k) {
        set<int> positions;
        for (int day = 1; day <= flowers.size(); day++) {
            int pos = flowers[day - 1];
            // positions.insert(pos);
            // auto iter = positions.find(pos);
            auto iter = positions.insert(pos).first;
            if (iter != positions.begin()) {
                int left = *(--iter);
                if (pos - left == k + 1)
                    return day;
                iter++;
            }
            if (++iter != positions.end()) {
                int right = *iter;
                if (right - pos == k + 1)
                    return day;
            }
        }
        return -1;
    }
};
// Solution 2: Sliding Window O(n)
// The idea is to use an array days[] to record each position’s flower’s blooming day. 
// That means days[i] is the blooming day of the flower in position i+1. 
// We just need to find a subarray days[left, left+1,..., left+k, right] which satisfies: 
// for any i = left+1,..., left+k, we can have days[left] < days[i] && days[right] < days[i]. 
// Then, the result is max(days[left], days[right]).
class Solution {
public:
    int kEmptySlots(vector<int>& flowers, int k) {
        vector<int> days(flowers.size());
        for (int i = 0; i < flowers.size(); i++)
            days[flowers[i] - 1] = i + 1;
        int left = 0, right = k + 1, res = INT_MAX;
        for (int i = 1; right < flowers.size(); i++) {
            if (days[i] > days[left] && days[i] > days[right])
                continue;
            iLongest Substring with At Most K Distinct Charactersf (i == right)
                res = min(res, max(days[left], days[right]));
            left = i;
            right = i + k + 1;
        }
        return res == INT_MAX ? -1 : res;
    }
};
// Longest Substring with At Most K Distinct Characters
class Solution {
public:
    int lengthOfLongestSubstringKDistinct(string s, int k) {
        unordered_map<char, int> cache;
        int max_len = 0, start = 0, count = 0;
        for (int end = 0; end < s.size(); end++) {
            char c = s[end];
            if (!cache.count(c))
                count++;
            cache[c]++;
            while (count > k) { // count可以換成cache.size()
                cache[s[start]]--;
                if (cache[s[start]] == 0) {
                    cache.erase(s[start]);
                    count--;
                }
                start++;
            }
            max_len = max(max_len, end - start + 1);
        }
        return max_len;
    }
};
// Next Closest Time
// Given a time represented in the format "HH:MM", form the next closest time by reusing the current digits.
// Input: "19:34" Output: "19:39"
// Input: "23:59" Output: "22:22"
// Solution 1: Binary Search
class Solution {
public:
    string nextClosestTime(string time) {
        int hour = stoi(time.substr(0, 2));
        int minute = stoi(time.substr(3, 2));
        set<int> digits;
        digits.insert(time[0] - '0');
        digits.insert(time[1] - '0');
        digits.insert(time[3] - '0');
        digits.insert(time[4] - '0');
        vector<int> hours, minutes;
        for (int i : digits) {
            for (int j : digits) {
                int num = i * 10 + j;
                if (num <= 23)
                    hours.push_back(num);
                if (num <= 59)
                    minutes.push_back(num);
            }
        }
        sort(hours.begin(), hours.end());
        sort(minutes.begin(), minutes.end());
        // Find the first i which minutes[i] > minute
        int left = 0, right = minutes.size() - 1;
        while (left < right) {
            int mid = (left + right) / 2;
            if (minutes[mid] > minute)
                right = mid;
            else
                left = mid + 1;
        }
        if (minutes[left] > minute)
            return time.substr(0, 2) + ":" + (minutes[left] < 10 ? "0" : "") + to_string(minutes[left]);
        // Find the first i which hours[i] > hour
        left = 0, right = hours.size() - 1;
        while (left < right) {
            int mid = (left + right) / 2;
            if (hours[mid] > hour)
                right = mid;
            else
                left = mid + 1;
        }
        if (hours[left] > hour)
            return (hours[left] < 10 ? "0" : "") + to_string(hours[left]) + ":" + (minutes[0] < 10 ? "0" : "") + to_string(minutes[0]);
        else
            return (hours[0] < 10 ? "0" : "") + to_string(hours[0]) + ":" + (minutes[0] < 10 ? "0" : "") + to_string(minutes[0]);
    }
};
// Solution 2: Just turn the clock forwards one minute at a time until you reach a time with the original digits.
class Solution {
public:
    string nextClosestTime(string time) {
        int hour = stoi(time.substr(0, 2));
        int minute = stoi(time.substr(3, 2));
        set<int> digits;
        digits.insert(time[0] - '0');
        digits.insert(time[1] - '0');
        digits.insert(time[3] - '0');
        digits.insert(time[4] - '0');
        while (true) {
            minute += 1;
            if (minute == 60) {
                minute = 0;
                hour += 1;
                if (hour == 24)
                    hour = 0;
            }
            if (digits.count(minute % 10) && digits.count(minute / 10) && digits.count(hour % 10) && digits.count(hour / 10))
                return (hour < 10 ? "0" : "") + to_string(hour) + ":" + (minute < 10 ? "0" : "") + to_string(minute);
        }
    }
};
// License Key Formatting
// Given a number K, we would want to reformat the strings such that each group contains exactly K characters, except for the first group which could be shorter than K.
// Input: S = "2-5g-3-J", K = 2 Output: "2-5G-3J"
// Solution 1
class Solution {
public:
    string licenseKeyFormatting(string S, int K) {
        int count = 0;
        for (char c : S)
            if (c != '-')
                count++;
        int i = 0;
        string res = "";
        if (count == 0)
            return res;
        if (count % K != 0) {
            while (res.size() < count % K) {
                if (S[i] != '-') {
                    if (S[i] >= 'a' && S[i] <= 'z')
                        res += (S[i] + 'A' - 'a');
                    else
                        res += S[i];
                }
                i++;
            }
            res += '-';
        }
        while (i < S.size()) {
            int j = 0;
            while (i < S.size() && j < K) {
                if (S[i] != '-') {
                    if (S[i] >= 'a' && S[i] <= 'z')
                        res += (S[i] + 'A' - 'a');
                    else
                        res += S[i];
                    j++;
                }
                i++;
            }
            if (j == K) // Important!
                res += '-';
        }
        res.erase(res.size() - 1);
        return res;
    }
};
// Solution 2: Scan string backward
// Key observation: every (K+1)th character from the tail of the formatted string must be a '-'.
class Solution {
public:
    string licenseKeyFormatting(string S, int K) {
        string res;
        for (int i = S.size() - 1; i >= 0; i--) {
            if (S[i] != '-') {
                if (res.size() % (K + 1) == K)
                    res += '-';
                res += toupper(S[i]);
            }
        }
        reverse(res.begin(), res.end());
        return res;
    }
};
// Repeated String Match
// Given two strings A and B, find the minimum number of times A has to be repeated such that B is a substring of it. If no such solution, return -1.
// For example, with A = "abcd" and B = "cdabcdab". Return 3.
// Solution 1: Keep appending until the length A is greater or equal to B.
class Solution {
public:
    int repeatedStringMatch(string A, string B) {
        int n = A.size(), m = B.size();
        int k = ceil(m * 1.0 / n) + 1;
        string C = "";
        for (int i = 0; i < k; i++)
            C += A;
        if (C.find(B) == -1)
            return -1;
        return (C.find(B) >= n || C.find(B) + m <= (k - 1) * n) ? (k - 1) : k;
    }
};
class Solution {
public:
    int repeatedStringMatch(string A, string B) {
        int n = A.size(), m = B.size();
        int k = ceil(m * 1.0 / n);
        string C = "";
        for (int i = 0; i < k; i++)
            C += A;
        if (C.find(B) == -1) {
            C += A;
            return (C.find(B) == -1) ? -1 : k + 1;
        } else
            return k;
    }
};
// Moving Average from Data Stream
// Given a stream of integers and a window size, calculate the moving average of all integers in the sliding window.
// For example,
// MovingAverage m = new MovingAverage(3);
// m.next(1) = 1
// m.next(10) = (1 + 10) / 2
// m.next(3) = (1 + 10 + 3) / 3
// m.next(5) = (10 + 3 + 5) / 3
class MovingAverage {
public:
    /** Initialize your data structure here. */
    MovingAverage(int size) {
        k = size;
        sum = 0;
    }
    
    double next(int val) {
        q.push(val);
        sum += val;
        if (q.size() > k) {
            sum -= q.front();
            q.pop();
        }
        return sum * 1.0 / q.size();
    }
private:
    queue<int> q;
    int k, sum;
};
/**
 * Your MovingAverage object will be instantiated and called as such:
 * MovingAverage obj = new MovingAverage(size);
 * double param_1 = obj.next(val);
*/
// Zigzag Iterator
// Given two 1d vectors, implement an iterator to return their elements alternately.
class ZigzagIterator {
public:
    ZigzagIterator(vector<int>& v1, vector<int>& v2) {
        if (!v1.empty())
            q.push(make_pair(v1.begin(), v1.end()));
        if (!v2.empty())
            q.push(make_pair(v2.begin(), v2.end()));
    }

    int next() {
        int res = *q.front().first;
        q.front().first++;
        if (q.front().first != q.front().second)
            q.push(q.front());
        q.pop();
        return res;
    }

    bool hasNext() {
        return !q.empty();
    }
private:
    queue<pair<vector<int>::iterator, vector<int>::iterator>> q;
};
/**
 * Your ZigzagIterator object will be instantiated and called as such:
 * ZigzagIterator i(v1, v2);
 * while (i.hasNext()) cout << i.next();
*/
// Binary Tree Longest Consecutive Sequence
// Given a binary tree, find the length of the longest consecutive sequence path along the parent-child connections.
class Solution {
public:
    int longestConsecutive(TreeNode* root) {
        int res = 0;
        longestConsecutive(root, INT_MAX, 0, res);
        return res;
    }
    void longestConsecutive(TreeNode* root, int parent, int path_len, int &res) {
        if (root == NULL)
            return;
        if (parent != INT_MAX && root->val == parent + 1)
            path_len++;
        else
            path_len = 1;
        res = max(res, path_len);
        longestConsecutive(root->left, root->val, path_len, res);
        longestConsecutive(root->right, root->val, path_len, res);
    }
};
// Sentence Screen Fitting (Tricky)
// Given a rows x cols screen and a sentence represented by a list of non-empty words, find how many times the given sentence can be fitted on the screen.
// 1. A word cannot be split into two lines.
// 2. The order of words in the sentence must remain unchanged.
// 3. Two consecutive words in a line must be separated by a single space.
// Time Limit Exceeded
class Solution {
public:
    int wordsTyping(vector<string>& sentence, int rows, int cols) {
        vector<int> length(sentence.size());
        int max_len = 0;
        for (int i = 0; i < sentence.size(); i++) {
            string word = sentence[i];
            max_len = max(max_len, (int)word.size());
            length[i] = word.size();
        }
        if (max_len > cols)
            return 0;
        int i = 0, j = 0, k = 0, res = 0;
        while (i < rows) {
            if (j + length[k] > cols) {
                i++;
                j = 0;
                continue;
            }
            j += (length[k++] + 1);
            if (k == sentence.size()) {
                res++;
                k = 0;
            }
        }
        return res;
    }
};
// C++ memorized search
// Use num to represent how many words can be put in the screen. 
// Use a map<i, cnt> to record for each line how many words cnt can be put when starting with word i. 
// So when we scan each line of the screen, we first get the starting word should be put on this line. 
// If this starting words is already in the map, then just read it; otherwise, create a new entry in this map.
class Solution {
public:
    int wordsTyping(vector<string>& sentence, int rows, int cols) {
        int num = 0, n = sentence.size();
        unordered_map<int, int> cache;
        for (int i = 0; i < rows; i++) {
            int start = num % n;
            if (!cache.count(start)) {
                int cnt = 0, j = 0, k = start;
                while (j + sentence[k].size() <= cols) {
                    j += (sentence[k++].size() + 1);
                    k %= n;
                    cnt++;
                }
                cache[start] = cnt;
            }
            num += cache[start];
        }
        return num / n;
    }
};
// Word Squares
// Given a set of words (without duplicates), find all word squares you can build from them.
// A sequence of words forms a valid word square if the kth row and column read the exact same string.
// All words will have the exact same length.
// Solution 1: Trie + DFS
class Solution {
public:
    class Trie {
        struct TrieNode {
            bool isWord;
            TrieNode* children[26];
            TrieNode() {
                isWord = false;
                for (int i = 0; i < 26; i++)
                    children[i] = NULL;
            }
        };
    public:
        Trie() {
            root = new TrieNode();
        }
        void insert(string word) {
            TrieNode *p = root;
            for (char c : word) {
                if (p->children[c - 'a'] == NULL)
                    p->children[c - 'a'] = new TrieNode();
                p = p->children[c - 'a'];
            }
            p->isWord = true;
        }
        vector<string> startsWith(string prefix) {
            TrieNode *p = root;
            for (char c : prefix) {
                p = p->children[c - 'a'];
                if (p == NULL)
                    return vector<string>();
            }
            vector<string> res;
            traversal(p, prefix, res);
            return res;
        }
    private:
        TrieNode *root;
        void traversal(TrieNode *t, string path, vector<string>& res) {
            if (t->isWord)
                res.push_back(path);
            for (int i = 0; i < 26; i++)
                if (t->children[i])
                    traversal(t->children[i], path + (char)('a' + i), res);
        }
    };
    vector<vector<string>> wordSquares(vector<string>& words) {
        if (words.empty())
            return vector<vector<string>>();
        const int n = words[0].size();
        Trie trie;
        for (string word : words)
            trie.insert(word);
        vector<string> square(n);
        vector<vector<string>> res;
        dfs(0, n, trie, square, res);
        return res;
    }
    void dfs(int k, const int n, Trie& trie, vector<string> square, vector<vector<string>>& res) {
        if (k == n) {
            res.push_back(square);
            return;
        }
        string prefix = square[k];
        for (string word : trie.startsWith(prefix)) {
            square[k] = word;
            for (int i = k + 1; i < n; i++)
                if (square[i].size() <= k)
                    square[i] += square[k][i];
                else
                    square[i][k] = square[k][i];
            dfs(k + 1, n, trie, square, res);
        }
    }
};
// Solution 2: Hash Table + DFS
// use unordered_map<string, vector<string>>
class Solution {
public:
    vector<vector<string>> wordSquares(vector<string>& words) {
        if (words.empty())
            return vector<vector<string>>();
        const int n = words[0].size();
        unordered_map<string, vector<string>> cache;
        for (string word : words)
            for (int i = 0; i < word.size(); i++)
                cache[word.substr(0, i)].push_back(word);
        vector<string> square(n);
        vector<vector<string>> res;
        dfs(0, n, cache, square, res);
        return res;
    }
    void dfs(int k, const int n, unordered_map<string, vector<string>>& cache, vector<string> square, vector<vector<string>>& res) {
        if (k == n) {
            res.push_back(square);
            return;
        }
        string prefix = "";
        for (int i = 0; i < k; i++)
            prefix += square[i][k];
        for (string word : cache[prefix]) {
            square[k] = word;
            dfs(k + 1, n, cache, square, res);
        }
    }    
};
// Range Sum Query 2D - Mutable (Tricky)
// Binary Indexed Tree 樹狀數(shù)組
class NumMatrix {
public:
    NumMatrix(vector<vector<int>> matrix) {
        n = matrix.size();
        m = n ? matrix[0].size() : 0;
        sums.resize(n + 1);
        for (int i = 0; i < n + 1; i++)
            sums[i].resize(m + 1);
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                add(i, j, matrix[i][j]);
    }
    int sumRegion(int row1, int col1, int row2, int col2) {
        return sum(row2, col2) - sum(row2, col1 - 1) - sum(row1 - 1, col2) + sum(row1 - 1, col1 - 1);
    }
    void update(int row, int col, int val) {
        add(row, col, val - sumRegion(row, col, row, col));
    }
    
private:
    vector<vector<int>> sums;
    int n, m;
    
    void add(int row, int col, int val) {
        int i = row + 1, j;
        while (i < n + 1) {
            j = col + 1;
            while (j < m + 1) {
                sums[i][j] += val;
                j += (j & -j);
            }
            i += (i & -i);
        }
    }
    int sum(int row, int col) {
        int i = row + 1, j, res = 0;
        while (i) {
            j = col + 1;
            while (j) {
                res += sums[i][j];
                j -= (j & -j);
            }
            i -= (i & -i);
        }
        return res;
    }
};
// Bomb Enemy (Tricky)
// Given a 2D grid, each cell is either a wall 'W', an enemy 'E' or empty '0' (the number zero), return the maximum enemies you can kill using one bomb.
// The bomb kills all the enemies in the same row and column from the planted point until it hits the wall since the wall is too strong to be destroyed.
// Note that you can only put the bomb at an empty cell.
// Solution: We do simply two traversals. 
// One from upper left to bottom right, for each spot we compute enemies to its left and up including itself. 
// The other traversal is from bottom right to upper left, we compute enemies to its right and down and in the same time we add them up all to find the maxKill.
class Solution {
public:
    int maxKilledEnemies(vector<vector<char>>& grid) {
        if (grid.size() == 0 || grid[0].size() == 0)
            return 0;
        const int n = grid.size(), m = grid[0].size();
        vector<vector<int> > count(n, vector<int>(m, 0));
        vector<int> top(m, 0);
        for (int i = 0; i < n; i++) {
            int left = 0;
            for (int j = 0; j < m; j++) {
                count[i][j] = top[j] + left + (grid[i][j] == 'E');
                if (grid[i][j] == 'E') {
                    top[j]++;
                    left++;
                } else if (grid[i][j] == 'W') {
                    top[j] = 0;
                    left = 0;
                }    
            }
        }
        vector<int> bottom(m, 0);
        for (int i = n - 1; i >= 0; i--) {
            int right = 0;
            for (int j = m - 1; j >= 0; j--) {
                count[i][j] += (bottom[j] + right);
                if (grid[i][j] == 'E') {
                    bottom[j]++;
                    right++;
                } else if (grid[i][j] == 'W') {
                    bottom[j] = 0;
                    right = 0;
                }    
            }
        }
        int res = 0;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                if (grid[i][j] == '0')
                    res = max(res, count[i][j]);
        return res;
    }
};
// UTF-8 Validation
// A character in UTF8 can be from 1 to 4 bytes long, subjected to the following rules:
// For 1-byte character, the first bit is a 0, followed by its unicode code.
// For n-bytes character, the first n-bits are all one's, the n+1 bit is 0, followed by n-1 bytes with most significant 2 bits being 10.
// Given an array of integers representing the data, return whether it is a valid utf-8 encoding.
// Note: The input is an array of integers. Only the least significant 8 bits of each integer is used to store the data. This means each integer represents only 1 byte of data.
class Solution {
public:
    bool validUtf8(vector<int>& data) {
        for (int i = 0; i < data.size(); i++) {
            int seq = data[i] & 0xFF;
            if ((seq >> 7) == 0) {
                continue;
            } else if ((seq >> 5) == 6) { // 110
                if (i + 1 >= data.size() || ((data[i + 1] & 0xFF) >> 6) != 2)
                    return false;
                i++;
            } else if ((seq >> 4) == 14) { // 1110
                if (i + 2 >= data.size() || ((data[i + 1] & 0xFF) >> 6) != 2 || ((data[i + 2] & 0xFF) >> 6) != 2)
                    return false;
                i += 2;
            } else if ((seq >> 3) == 30) { // 11110
                if (i + 3 >= data.size() || ((data[i + 1] & 0xFF) >> 6) != 2 || ((data[i + 2] & 0xFF) >> 6) != 2 || ((data[i + 3] & 0xFF) >> 6) != 2)
                    return false;
                i += 3;
            } else {
                return false;
            }
        }
        return true;
    }
};
// Decode String
// The encoding rule is: k[encoded_string], where the encoded_string inside the square brackets is being repeated exactly k times. 
// s = "3[a]2[bc]", return "aaabcbc".
// s = "3[a2[c]]", return "accaccacc".
class Solution {
public:
    string decodeString(string s) {
        string res;
        stack<pair<int, string>> brackets;
        int repeat = 0;
        for (char c : s) {
            if (c >= '0' && c <= '9') {
                repeat *= 10;
                repeat += (c - '0');
            } else if (c == '[') {
                brackets.push(make_pair(repeat, ""));
                repeat = 0;
            } else if (c == ']') {
                string cur = "";
                for (int i = 0; i < brackets.top().first; i++)
                    cur += brackets.top().second;
                brackets.pop();
                if (brackets.empty())
                    res += cur;
                else
                    brackets.top().second += cur;
            } else {
                if (brackets.empty())
                    res += c;
                else
                    brackets.top().second += c;
            }                
        }
        return res;
    }
};
// Plus One
// Given a non-negative integer represented as a non-empty array of digits, plus one to the integer.
// You may assume the integer do not contain any leading zero, except the number 0 itself.
// The digits are stored such that the most significant digit is at the head of the list.
class Solution {
public:
    vector<int> plusOne(vector<int>& digits) {
        if (digits.empty()) {
            digits.push_back(1);
            return digits;
        }
        int pos = digits.size() - 1;
        do {
            digits[pos]++;
            if (digits[pos] < 10)
                break;
            digits[pos] = 0;
            pos--;
        } while (pos >= 0);
        if (pos < 0)
            digits.insert(digits.begin(), 1);
        return digits;
    }
};
// Missing Ranges
// Given a sorted integer array where the range of elements are in the inclusive range [lower, upper], return its missing ranges.
// For example, given [0, 1, 3, 50, 75], lower = 0 and upper = 99, return ["2", "4->49", "51->74", "76->99"].
// Edge cases:
// [1,1,1]
// 1
// 1
// [-2147483648,-2147483648,0,2147483647,2147483647] 
// -2147483648
// 2147483647
// []
// 1
// 1
class Solution {
public:
    vector<string> findMissingRanges(vector<int>& nums, int lower, int upper) {
        vector<string> res;
        long long last = (long long)lower - 1;
        for (int num : nums) {
            if (num > last + 1)
                if (num == last + 2)
                    res.push_back(to_string(last + 1));
                else
                    res.push_back(to_string(last + 1) + "->" + to_string(num - 1));
            last = num;
        }
        if (last < upper)
            if (last == upper - 1)
                res.push_back(to_string(upper));
            else
                res.push_back(to_string(last + 1) + "->" + to_string(upper));
        return res;
    }
};
// Summary Ranges
// Given a sorted integer array without duplicates, return the summary of its ranges.
// Example:
// Input: [0,1,2,4,5,7]
// Output: ["0->2","4->5","7"]
class Solution {
public:
    vector<string> summaryRanges(vector<int>& nums) {
        vector<string> res;
        if (nums.empty())
            return res;
        int start = nums[0], last = nums[0];
        for (int i = 1; i < nums.size(); i++) {
            if (nums[i] > last + 1) {
                res.push_back(start == last ? to_string(start) : to_string(start) + "->" + to_string(last));
                start = nums[i];
            }
            last = nums[i];
        }
        res.push_back(start == last ? to_string(start) : to_string(start) + "->" + to_string(last));
        return res;
    }
};
// Android Unlock Patterns
// Given an Android 3x3 key lock screen and two integers m and n, where 1 ≤ m ≤ n ≤ 9, count the total number of unlock patterns of the Android lock screen, which consist of minimum of m keys and maximum n keys.
// Rules for a valid pattern:
// 1. Each pattern must connect at least m keys and at most n keys.
// 2. All the keys must be distinct.
// 3. If the line connecting two consecutive keys in the pattern passes through any other keys, the other keys must have previously selected in the pattern. No jumps through non selected key is allowed.
// 4. The order of keys used matters.
// Example: Given m = 1, n = 1, return 9.
class Solution {
public:
    int numberOfPatterns(int m, int n) {
        int res = 0;
        vector<vector<bool> > selected(3, vector<bool>(3, false));
        for (int i = 0; i < 3; i++)
            for (int j = 0; j < 3; j++)
                dfs(0, i, j, m, n, selected, res);
        return res;
    }
    int distance(int x1, int y1, int x2, int y2) {
        return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
    }
    void dfs(int k, int i, int j, const int m, const int n, vector<vector<bool> > selected, int &res) {
        selected[i][j] = true;
        if (k + 1 >= m)
            res++;
        if (k + 1 == n)
            return;
        for (int ii = 0; ii < 3; ii++)
            for (int jj = 0; jj < 3; jj++)
                if (!selected[ii][jj]) {
                    int d = distance(i, j, ii, jj);
                    if (d == 1 || d == 2 || d == 5 || (d == 4 && selected[(i + ii) / 2][(j + jj) / 2]) || (d == 8 && selected[(i + ii) / 2][(j + jj) / 2]))
                        dfs(k + 1, ii, jj, m, n, selected, res);
                }
    }
};
// The optimization idea is that 1,3,7,9 are symmetric, 2,4,6,8 are also symmetric. 
// Hence we only calculate one among each group and multiply by 4.
int numberOfPatterns(int m, int n) {
    vector<vector<bool> > selected(3, vector<bool>(3, false));
    int res1 = 0, res2 = 0, res3 = 0;
    dfs(0, 0, 0, m, n, selected, res1);
    dfs(0, 0, 1, m, n, selected, res2);
    dfs(0, 1, 1, m, n, selected, res3);
    return res1 * 4 + res2 * 4 + res3;
}
// Encode and Decode Strings
// Design an algorithm to encode a list of strings to a string. The encoded string is then sent over the network and is decoded back to the original list of strings.
// Solution: The rule is, for each str in strs, encode it as <length> + ‘@’ + str
class Codec {
public:
    // Encodes a list of strings to a single string.
    string encode(vector<string>& strs) {
        string encoded = "";
        for (string &str: strs) {
            int len = str.size();
            encoded += to_string(len) + "@" + str;
        }
        return encoded;
    }

    // Decodes a single string to a list of strings.
    vector<string> decode(string s) {
        vector<string> r;
        int head = 0;
        while (head < s.size())    {
            int at_pos = s.find_first_of('@', head);
            int len = stoi(s.substr(head, at_pos - head));
            head = at_pos + 1;
            r.push_back(s.substr(head, len));
            head += len;
        }
        return r;
    }
};
// The Skyline Problem
struct Building {
    int left;
    int right;
    int height;
    Building(int l, int r, int h): left(l), right(r), height(h) {}
    bool operator <(const Building &other) const {
        if (left == other.left)
            return (height < other.height);
        return left > other.left;
        // Ensure next_left >= cur_left
        // Ensure if next_left == cur_left, then next_height < cur_height
    }
};
class Solution {
public:
    vector<pair<int, int>> getSkyline(vector<vector<int>>& buildings) {
        if (buildings.empty())
            return vector<pair<int, int>>();
        vector<pair<int, int>> result;
        priority_queue<Building> pq;
        for (int i = 0; i < buildings.size(); i++)
            pq.push(Building(buildings[i][0], buildings[i][1], buildings[i][2]));
        int cur_left = pq.top().left, cur_right = pq.top().right, cur_height = pq.top().height;
        pq.pop();
        while (!pq.empty()) {
            int next_left = pq.top().left, next_right = pq.top().right, next_height = pq.top().height;
            pq.pop();
            if (next_left > cur_right) {
                result.push_back(make_pair(cur_left, cur_height));
                result.push_back(make_pair(cur_right, 0));
                cur_left = next_left; cur_right = next_right; cur_height = next_height;
            } else if (next_left == cur_right) {
                if (next_height == cur_height) {
                    cur_right = next_right;
                } else {
                    result.push_back(make_pair(cur_left, cur_height));
                    cur_left = next_left; cur_right = next_right; cur_height = next_height;
                }
            } else if (next_left == cur_left) {
                if (next_right > cur_right)
                    pq.push(Building(cur_right, next_right, next_height));
            } else {
                // cur_left < next_left < cur_right
                if (next_height == cur_height) {
                    cur_right = max(cur_right, next_right);
                } else if (next_height < cur_height) {
                    if (next_right > cur_right)
                        pq.push(Building(cur_right, next_right, next_height));
                } else {
                    result.push_back(make_pair(cur_left, cur_height));
                    pq.push(Building(next_left, cur_right, cur_height));
                    cur_left = next_left; cur_right = next_right; cur_height = next_height;
                }
            }      
        }
        result.push_back(make_pair(cur_left, cur_height));
        result.push_back(make_pair(cur_right, 0));
        return result;
    }
};
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末眷唉,一起剝皮案震驚了整個(gè)濱河市捂龄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奏候,老刑警劉巖岩瘦,帶你破解...
    沈念sama閱讀 222,865評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件未巫,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡启昧,警方通過查閱死者的電腦和手機(jī)叙凡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來密末,“玉大人握爷,你說我怎么就攤上這事⊙侠铮” “怎么了新啼?”我有些...
    開封第一講書人閱讀 169,631評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)刹碾。 經(jīng)常有香客問我师抄,道長(zhǎng),這世上最難降的妖魔是什么教硫? 我笑而不...
    開封第一講書人閱讀 60,199評(píng)論 1 300
  • 正文 為了忘掉前任叨吮,我火速辦了婚禮,結(jié)果婚禮上瞬矩,老公的妹妹穿的比我還像新娘茶鉴。我一直安慰自己,他們只是感情好景用,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評(píng)論 6 398
  • 文/花漫 我一把揭開白布涵叮。 她就那樣靜靜地躺著,像睡著了一般伞插。 火紅的嫁衣襯著肌膚如雪割粮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,793評(píng)論 1 314
  • 那天媚污,我揣著相機(jī)與錄音舀瓢,去河邊找鬼。 笑死耗美,一個(gè)胖子當(dāng)著我的面吹牛京髓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播商架,決...
    沈念sama閱讀 41,221評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼堰怨,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了蛇摸?” 一聲冷哼從身側(cè)響起备图,我...
    開封第一講書人閱讀 40,174評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后揽涮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抠藕,經(jīng)...
    沈念sama閱讀 46,699評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評(píng)論 3 343
  • 正文 我和宋清朗相戀三年绞吁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了幢痘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,918評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡家破,死狀恐怖颜说,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情汰聋,我是刑警寧澤门粪,帶...
    沈念sama閱讀 36,573評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站烹困,受9級(jí)特大地震影響玄妈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜髓梅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評(píng)論 3 336
  • 文/蒙蒙 一拟蜻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧枯饿,春花似錦酝锅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蟋字,卻和暖如春稿蹲,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鹊奖。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工苛聘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人嫉入。 一個(gè)月前我還...
    沈念sama閱讀 49,364評(píng)論 3 379
  • 正文 我出身青樓焰盗,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親咒林。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,336評(píng)論 25 707
  • 小灶四班最佳作品集結(jié) 一爷光、開始時(shí)間:20180101 恭喜@林妖妖在1月1日的讀書任務(wù)中獲得最佳垫竞,...
    泉布閱讀 959評(píng)論 0 0
  • 歡迎關(guān)注我的公眾號(hào):讀書主義 更多精彩等著你! 這個(gè)讀書方法,可能會(huì)顛覆你對(duì)讀書以往的認(rèn)知|開卷 或許讀書已經(jīng)成為...
    米米粒粒閱讀 34,615評(píng)論 9 209
  • 以前欢瞪,我有一盆文竹 雖然嬌柔 但活烙,生機(jī)蓬勃,綠意盎然 宛如心中的愛情 美好遣鼓,令人幸福啸盏,神往。 有一天骑祟,我把它放在了...
    十五夜月閱讀 527評(píng)論 0 4
  • Today is Thursday. I am going to read a new book, The Car...
    Mr_Oldman閱讀 232評(píng)論 0 0