Categories
不学无术

654. Maximum Binary Tree

Given an integer array with no duplicates. A maximum tree building on this array is defined as follow:

  1. The root is the maximum number in the array.
  2. The left subtree is the maximum tree constructed from left part subarray divided by the maximum number.
  3. The right subtree is the maximum tree constructed from right part subarray divided by the maximum number.

Construct the maximum tree by the given array and output the root node of this tree.
 

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* subMaxBinTree(vector<int>::iterator begin, vector<int>::iterator end)
    {
        if (begin == end)
            return nullptr;
        auto maxElemIt = std::max_element(begin, end);
        TreeNode* root = new TreeNode(*maxElemIt);
        root->left = subMaxBinTree(begin, maxElemIt);
        root->right = subMaxBinTree(maxElemIt+1, end);
        return root;
    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        if (nums.empty())
            return nullptr;
        return subMaxBinTree(nums.begin(), nums.end());
    }
};

 

Categories
木有技术

LeetCode 89. Gray Code

Divide and conquer!
Add a leading 0 or 1 bit to your existing results so here comes two sub-results: 0{xxxxx} and 1{xxxxx}. How to merge them? Just keep the first sub group and append the second group items reversely so that there is only a 1-bit difference between the end of group 0 and “start” of group 2.

class Solution {
public:
    vector<int> grayCode(int n) {
        if (n == 0)
            return { 0 };
        vector<int> results = { 0, 1 };
        for (size_t i = 1; i < n; ++i)
        {
            for (int j = results.size() - 1; j >= 0; --j)
            {
                results.push_back(results[j] + (1 << i));
            }
        }
        return results;
    }
};

 

Categories
木有技术

LeetCode 402. Remove K Digits

https://leetcode.com/problems/remove-k-digits/description/
如果直接用DFS做的话轻轻松松就会stack overflow。
这道题可以用贪心法,题目换个思路说就是尽可能保证得到的数字是递增的。在拿到一个新数字时,尽可能(只要还能删)把该数字之前的比它大的数字移掉。
贪心法之所以能用是因为我们去尽量保证了a1<a2< …< x< y,如果这些个数字里要选一个删掉的话,肯定是删掉y带来的结果最好。

class Solution {
public:
	string removeKdigits(string num, int k) {
		const int digits = num.size() - k;
        char* stack = new char[num.size()]; // mem leak but I DONT CARE!
        int top = 0;
        for (int i = 0; i < num.size(); ++i)
        {
            char c = num[i];
            while (top > 0 && stack[top-1] > c && k > 0)
            {
                top--;
                k--;
            }
            stack[top++] = c;
        }
        int idx = 0;
        while (idx < digits && stack[idx] == '0')
            idx++;
        return idx == digits ? "0" : string(stack + idx, digits - idx);
	}
};

 

Categories
木有技术

LeetCode 269. Alien Dictionary

There is a new alien language which uses the latin alphabet. However, the order among letters are unknown to you. You receive a list of non-empty words from the dictionary, where words are sorted lexicographically by the rules of this new language. Derive the order of letters in this language.
Example 1:

Input:
[
  "wrt",
  "wrf",
  "er",
  "ett",
  "rftt"
]
Output:"wertf"

Example 2:

[
  "z",
  "x"
]
>Output: "zx"

Example 3:

[
  "z",
  "x",
  "z"
]
Output:""

Note:

  1. You may assume all letters are in lowercase.
  2. You may assume that if a is a prefix of b, then a must appear before b in the given dictionary.
  3. If the order is invalid, return an empty string.
  4. There may be multiple valid order of letters, return any one of them is fine.

 

Solution:

The solution is to build a directed map and find the topological ordering of the characters. Once the map is built, we can always find the “terminal” character which has no succeeding, i.e. the out-degree of that node would be zero. The we remove the character (the node and its edges) from the map and try to find the next such character, so on so forth.

[
  "wrt",
  "wrf",
  "er",
  "ett",
  "rftt"
]

For example,  the map built will be:

t: {f}
w: {e}
r: {t}
e: {r}
f: {}
class Solution {
private:
    map<char, set<char>> ch_map;
    void build(const string& w1, const string& w2)
    {
        const int len = std::min(w1.size(), w2.size());
        int i = 0;
        for (i = 0; i < len; ++i)
        {
            if (ch_map.count(w1[i]) == 0)
                ch_map[w1[i]] = set<char>();
            if (ch_map.count(w2[i]) == 0)
                ch_map[w2[i]] = set<char>();
            if (w1[i] != w2[i])
            {
                ch_map[w1[i]].insert(w2[i]);
                break;
            }
        }
        for (; i < w1.size() || i < w2.size(); ++i)
        {
            if (i < w1.size() && ch_map.count(w1[i]) == 0)
                ch_map[w1[i]] = set<char>();
            if (i < w2.size() && ch_map.count(w2[i]) == 0)
                ch_map[w2[i]] = set<char>();
        }
    }
public:
    string alienOrder(vector<string>& words) {
        if (words.empty()) return string();
        if (words.size() == 1) return words[0];
        for (int i = 0; i < words.size() - 1; ++i)
        {
            build(words[i], words[i+1]);
        }
        string result;
        result.reserve(26);
        while (!ch_map.empty())
        {
            bool found = false;
            for (auto it : ch_map)
            {
                if (it.second.empty())
                {
                    found = true;
                    result = it.first + result;
                    break;
                }
            }
            ch_map.erase(result[0]);
            if (!found) return string();  //not found
            for (auto& it : ch_map)
            {
                it.second.erase(result[0]);
            }
        }
        return result;
    }
};

 
 

Categories
木有技术

LeetCode 611. Valid Triangle Number

https://leetcode.com/problems/valid-triangle-number/description/
有点类似3Sum的题目。形成三角形的充要条件是最小两边之和大于第三边。可以先给数组排序,然后确定一个最大边,然后在它左边找另外两边。
时间复杂度是O(n*log(n) + n^2) = O(n^2)

class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int count = 0;
        for (int i = nums.size() - 1; i >= 0; --i)
        {
            // two sum (x + y) > nums[i]
            int j = 0;
            int k = i - 1;
            while (j < k)
            {
                if (nums[j] + nums[k] <= nums[i])
                {
                    j++;
                    continue;
                }
                count += (k - j);
                k--;
            }
        }
        return count;
    }
};

 
 

Categories
木有技术

LeetCode 523. Continuous Subarray Sum

https://leetcode.com/problems/continuous-subarray-sum/description/
这道题跟https://leetcode.com/problems/subarray-sum-equals-k/description/ 其实是很像的,但本题的特点就是corner case非常多…

class Solution {
public:
    bool checkSubarraySum(vector<int>& nums, int k) {
        if (k < 0)
            k = -1 * k;
        else if (k == 0)
        {
            // check if there's continuous zeroes
            bool has_zero = false;
            for (int num : nums)
            {
                if (num == 0)
                {
                    if (has_zero == true)
                        return true;
                    has_zero = true;
                }
                else
                    has_zero = false;
            }
            return false;
        }
        if (k == 1 && nums.size() > 1)  // tricky but...
            return true;
        int sum = 0;
        unordered_set<int> sum_records;
        vector<int> targets = {k};
        int last_num = INT32_MAX;
        sum_records.insert(0);
        for (int num : nums)
        {
            sum += num;
            sum_records.insert(sum);
            if (last_num == 0 && num == 0)
                return true;    // n = 0
            while (targets.back() + k <= sum)
                targets.push_back(targets.back() + k);  // prvents calculating dup multiplies
            for (int target : targets)
            {
                if (num != target && sum_records.count(sum - target) > 0)
                    return true;
            }
            last_num = num;
        }
        return false;
    }
};

 

Categories
不学无术

LeetCode 560. Subarray Sum Equals K

https://leetcode.com/problems/subarray-sum-equals-k/description/
O(N^2)的方法想必所有人都会,这里有个用到prefix sum的O(N)方法。
试想一下,如果当前检查到end位置且目前所有项的和为sum,如果有那么一个(start, end)子序列的和为k,那么肯定有一个(0, start-1)的序列它的和是sum – k.

[a, b, c] \___k__/
[a, b, c, d, e, f]
/sum - k\
class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int, int> cum_sums;   // <cum_sum, count>
        cum_sums[0] = 1;
        int sum = 0;
        int count = 0;
        for (int i = 0; i < nums.size(); ++i)
        {
            sum += nums[i];
            if (cum_sums.count(sum - k) > 0)
                count += cum_sums[sum - k];
            cum_sums[sum]++;
        }
        return count;
    }
};

 

Categories
不学无术

LeetCode LIS系列 (Longest Increasing Path in a Matrix)

类似的东西还有:
674. Longest Continuous Increasing Subsequence
https://leetcode.com/problems/longest-continuous-increasing-subsequence/description/
300. Longest Increasing Subsequence
https://leetcode.com/problems/longest-increasing-subsequence/description/
longest path increasing by 1
https://www.geeksforgeeks.org/find-the-longest-path-in-a-matrix-with-given-constraints/
 
下面的代码是这个题的:

329. Longest Increasing Path in a Matrix

https://leetcode.com/problems/longest-increasing-path-in-a-matrix/description/ 
主要思路就是瞎JB搜索,不过某一个位置的结果可以记录下来给后续的重复搜索使用。

class Solution {
public:
	int subLIP(vector<vector<int>>& matrix, vector<vector<int>>& sub_results, int row, int col)
	{
		if (row < 0 || row >= matrix.size())
			return 0;
		if (col < 0 || col >= matrix[0].size())
			return 0;
		if (sub_results[row][col] != -1)
			return sub_results[row][col];
		// go left
		int maxResult = -1;
		if (col > 0 && matrix[row][col - 1] > matrix[row][col])
			maxResult = max(maxResult, 1 + subLIP(matrix, sub_results, row, col - 1));
		// go right
		if (col < matrix[0].size() - 1 && matrix[row][col + 1] > matrix[row][col])
			maxResult = max(maxResult, 1 + subLIP(matrix, sub_results, row, col + 1));
		// go up
		if (row > 0 && matrix[row - 1][col] > matrix[row][col])
			maxResult = max(maxResult, 1 + subLIP(matrix, sub_results, row - 1, col));
		// go down
		if (row < matrix.size() - 1 && matrix[row + 1][col] > matrix[row][col])
			maxResult = max(maxResult, 1 + subLIP(matrix, sub_results, row + 1, col));
		sub_results[row][col] = max(1, maxResult);
		return sub_results[row][col];
	}
	int longestIncreasingPath(vector<vector<int>>& matrix) {
		vector<vector<int>> sub_results;
		sub_results.resize(matrix.size());
		for (int i = 0; i < matrix.size(); ++i)
		{
			sub_results[i].resize(matrix[0].size(), -1);   // -1 means unknown
		}
		int result = 0;
		for (int r = 0; r < matrix.size(); ++r)
		{
			for (int c = 0; c < matrix[r].size(); ++c)
			{
				result = max(result, subLIP(matrix, sub_results, r, c));
			}
		}
		return result;
	}
};

 

Categories
未分类

LeetCode 128. Longest Consecutive Sequence

https://leetcode.com/problems/longest-consecutive-sequence/description/

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        unordered_set<int> all_nums;
        unordered_map<int, int> unions_rev; // <end_idx, start_idx>
        unordered_map<int, int> unions;     // <start_idx, end_idx>
        int max_length = 0;
        for (int num : nums)
        {
            auto it_r_union = unions_rev.find(num - 1);
            auto it_union = unions.find(num + 1);
            int start_idx = num;
            int end_idx = num;
            if (all_nums.find(num) != all_nums.end())
                continue;
            if (it_union != unions.end() && it_r_union != unions_rev.end())
            {
                // [RRR] num [SSS]
                start_idx = it_r_union->second;
                end_idx = it_union->second;
                unions_rev.erase(it_r_union);
                unions.erase(start_idx);
                unions.erase(it_union);
                unions_rev.erase(end_idx);
            }
            else if (it_union != unions.end())
            {
                // num [SSS]
                end_idx = it_union->second;
                unions.erase(it_union);
                unions_rev.erase(end_idx);
            }
            else if (it_r_union != unions_rev.end())
            {
                // [RRR] num
                start_idx = it_r_union->second;
                unions_rev.erase(it_r_union);
                unions.erase(start_idx);
            }
            unions[start_idx] = end_idx;
            unions_rev[end_idx] = start_idx;
            if (end_idx - start_idx + 1 > max_length)
            {
                max_length = end_idx - start_idx + 1;
            }
            all_nums.insert(num);
        }
        return max_length;
    }
};

 

Categories
不学无术

LeetCode 200. Number of Islands

https://leetcode.com/problems/number-of-islands/description/
DFS of a map, O(N^2)

class Solution {
public:
    bool visit(vector<vector<char>>& grid, int row, int col)
    {
        // if has any island, return true
        // DFS on grid
        const int rows = grid.size();
        if (rows == 0 || row >= rows || row < 0)
            return false;
        const int cols = grid[0].size();
        if (cols == 0 || col >= cols || col < 0)
            return false;
        if (grid[row][col] == 'V')
            return false;
        else if (grid[row][col] == '0')
            return false;
        grid[row][col] = 'V';
        visit(grid, row, col-1);
        visit(grid, row-1, col);
        visit(grid, row+1, col);
        visit(grid, row, col+1);
        return true;
    }
    int numIslands(vector<vector<char>>& grid) {
        // mark visited as 'V'
        int result = 0;
        for (int row = 0; row < grid.size(); ++row)
        {
            for (int col = 0; col < grid[0].size(); ++col)
            {
                if (grid[row][col] == 'V' || grid[row][col] == '0')
                {
                    continue;
                }
                if (visit(grid, row, col))
                    result++;
            }
        }
        return result;
    }
};