Categories
未分类

LeetCode 347. Top K Frequent Elements

https://leetcode.com/problems/top-k-frequent-elements/description/
hash map + heap
Time complicity: O(N + logk)

struct KvPair
{
    int key = 0;
    int val = 0;
};
class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> counts;
        for (int num : nums)
        {
            counts[num]++;
        }
        auto comp = [](const KvPair& lhs, const KvPair& rhs){
            return lhs.val > rhs.val;
        };
        priority_queue<KvPair, vector<KvPair>, decltype(comp)> pri_q(comp);
        for (auto& it : counts)
        {
            pri_q.push({it.first, it.second});
            if (pri_q.size() > k)
                pri_q.pop();
        }
        vector<int> results;
        while (!pri_q.empty())
        {
            results.push_back(pri_q.top().key);
            pri_q.pop();
        }
        return results;
    }
};

 

Categories
未分类

LeetCode 110. Balanced Binary Tree

https://leetcode.com/problems/balanced-binary-tree/description/

/**
 * 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:
    int maxDepth(TreeNode* root, int currDepth) {
        int left_depth = (root->left == nullptr) ? currDepth : maxDepth(root->left, currDepth + 1);
        int right_depth = (root->right == nullptr) ? currDepth : maxDepth(root->right, currDepth + 1);
        if (left_depth == -1 || right_depth == -1)
            return -1;
        if (left_depth - right_depth > 1 ||
            right_depth - left_depth > 1)
            return -1;
        return max(left_depth, right_depth);
    }
    bool isBalanced(TreeNode* root) {
        if (root == nullptr)
            return true;
        if (maxDepth(root, 0) == -1)
            return false;
        return true;
    }
};

 

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;
    }
};

 

Categories
木有技术

LeetCode 23. Merge k Sorted Lists

https://leetcode.com/problems/merge-k-sorted-lists/description/
Use max heap, the time complexity is O( log(k) * N )

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        if (lists.empty())
            return nullptr;
        auto comparor = [](ListNode* lhs, ListNode* rhs) {
            return lhs->val > rhs->val;
        };
        priority_queue<ListNode*, vector<ListNode*>, decltype(comparor)> pri_queue(comparor);
        // perpare queue with K items
        for(auto& list : lists)
        {
            if (list != nullptr)
                pri_queue.push(list);
        }
        ListNode* head = new ListNode(-1);
        ListNode* prev = head;
        ListNode* current = nullptr;
        while (!pri_queue.empty())
        {
            current = pri_queue.top();
            prev->next = current;
            ListNode* next = current->next;
            pri_queue.pop();
            if (next != nullptr)
                pri_queue.push(next);
            prev = current;
        }
        return head->next;
    }
};

 

Categories
木有技术

LeetCode 222. Count Complete Tree Nodes

https://leetcode.com/problems/count-complete-tree-nodes/description/
简单的二分法分治,探测(子)树的左右侧是否相等即可。
(下面代码没实现)想要更快的话,其实自从第一次算出左侧的深度后,后面的左测深度直接可以通过减法求出,不用再去探测一次了。

/**
 * 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:
    int countLevel(TreeNode* root, bool to_left) {
        int count = 0;
        while (root != nullptr)
        {
            count++;
            root = to_left ? root->left : root->right;
        }
        return count;
    }
    int countNodes(TreeNode* root) {
        if (root == nullptr)
            return 0;
        int lvl_left = countLevel(root, true);
        int lvl_right = countLevel(root, false);
        if (lvl_left == lvl_right)
        {
            // finally
            return (1 << lvl_left) - 1; // 2^n - 1
        }
        else
        {
            return 1 + countNodes(root->left) + countNodes(root->right);
        }
    }
};

 

Categories
工作

No core will be dumped when calling exit() in a signal handler

The customized abnormal signal handler (e.g. SIGSEGV handler) will function abnormally if we call exit() inside the handler: the program will exit “as normal” however it did had some severe memory issue.
See code snippet below, try to run with / without “X” argument.

/* exit example */
#include <stdio.h>      /* printf, fopen */
#include <stdlib.h>     /* exit, EXIT_FAILURE */
#include <signal.h>     /* signal */
#include <string.h>
bool disable_exit = false;
void InitiateAbnormalShutdown()
{
    printf("ABNORMAL SHUTDOWN!!!\n");
    if (!disable_exit)
        exit(EXIT_FAILURE);
}
void AbnormalSignalHandler(int signo)
{
    signal(signo, SIG_DFL);
    InitiateAbnormalShutdown();
    raise(signo);
}
bool give_me_an_error()
{
    int* test = new int;
    *test = 500;
    delete test;
    test = NULL;
    *test = 900;
    if (*test > 500)
    {
        return false;
    }
    return true;
}
int main(int argc, char *argv[])
{
    if (argc > 1)
    {
        printf("arg == %s\n", argv[1]);
        if (strcmp(argv[1], "X") == 0)
        {
            printf("disable exit on abnormal handler...\n");
            disable_exit = true;
        }
    }
    signal(SIGSEGV, AbnormalSignalHandler);
    give_me_an_error();
    return 0;
}

Output:

bowei.he:/sandbox/bowei.he/temp$ ./sigf
ABNORMAL SHUTDOWN!!!
bowei.he:/sandbox/bowei.he/temp$ ./sigf X
arg == X
disable exit on abnormal handler...
ABNORMAL SHUTDOWN!!!
Segmentation fault (core dumped)

 
 

Categories
不学无术

LeetCode 76. Minimum Window Substring

76. Minimum Window Substring
思路:
构造一个哈希表结构统计我们的需求,也就是字符串t中每个字符的数量,方便起见如果有需求则哈希表的对应值-1。另外存储一下当前解的起始位置START以及最优解的位置。
扫描字符串s,在位置s[i]时如果能够满足需求(即哈希表中没有负值),则从START开始清除无用的字符直至无法满足需求位置。比如需求是A:1, B:2,START开始的字符是DEFBAB,则清除DEF。清除完成后更新START值并跟当前已知的最优解比较,更新最优解。
啰嗦一句,似乎相当一部分substring类型的题目都能用hash table + two pointers的方式解决。

class Solution {
public:
    static string minWindow(string s, string t) {
        int count_map[128] = {0};
        set<char> req_set;
        int start_index = -1, min_start_index = 0;
        int min_end_index = INT_MAX;
        for (const char& c : t)
        {
            count_map[c] --;
            req_set.insert(c);
        }
        for (int i = 0; i < s.size(); ++i)
        {
            const char c = s[i];
            count_map[c] ++;
            bool require_sufficed = true;
            for (const char& c : req_set)
            {
                if (count_map[c] < 0)
                {
                    require_sufficed = false;
                    break;
                }
            }
            if (!require_sufficed) continue;
            // clear left
            for (int j = start_index + 1; j <= i; ++j)
            {
                if (--count_map[s[j]] < 0)
                {
                    start_index = j;
                    break;
                }
                start_index = j;
            }
            if (i - start_index < min_end_index - min_start_index)
            {
                min_start_index = start_index;
                min_end_index = i;
            }
        }
        if (min_end_index == INT_MAX)
            return "";
        else
            return s.substr(min_start_index, min_end_index - min_start_index + 1);
    }
};

 

Categories
不学无术

LeetCode 432. All O`one Data Structure

几万年没做LeetCode的题了,更新一下。
https://leetcode.com/problems/all-oone-data-structure/description/
这道题的思路是用一个双向链表(list)来存储一个以value排序的数据结构,使用哈希表(unordered_map)来存储key到链表iterator的映射:

需要注意特殊处理value=1的Node的情况。
代码写得比较毛糙,但是确实是O(1)的复杂度,如果要优化的话map的插入可以用emplace()之类的。
注意:除了value=1的节点,其余节点的keys为空的时候要把该节点删除掉,否则getMaxKey()和getMinKey()就需要O(n)的遍历操作了。

struct KvNode
{
    unordered_set<string> keys;
    int value = 1;
};
class AllOne {
private:
    list<KvNode> value_key;     // arranged by val in ascending order
    using list_it_t = list<KvNode>::iterator;
    unordered_map<string, list_it_t> val_map;
    list_it_t init_node;    //node with value one
public:
    /** Initialize your data structure here. */
    AllOne() {
        value_key.push_back(KvNode());
        init_node = value_key.begin();
    }
    /** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
    void inc(const string& key) {
        if (val_map.find(key) == val_map.end())
        {
            // `create' new node with value 1
            init_node->keys.insert(key);
            val_map[key] = init_node;
        }
        else
        {
            // find existing node
            auto node_it = val_map[key];
            node_it->keys.erase(key);   //remove from current bulk
            auto next_it = std::next(node_it, 1);
            if (next_it == value_key.end() ||
                 next_it->value != node_it->value + 1)
            {
                // no valid valued bulk, create one
                KvNode node;
                node.keys.insert(key);
                node.value = node_it->value + 1;
                val_map[key] = value_key.insert(next_it, node);
            }
            else
            {
                next_it->keys.insert(key);
                val_map[key] = next_it;
            }
            if (node_it->keys.empty() && node_it->value != 1)
            {
                // remove node_it
                value_key.erase(node_it);
            }
        }
    }
    /** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
    void dec(string key) {
        auto it_val_map = val_map.find(key);
        if (it_val_map == val_map.end())
        {
            // key does not exist
            return;
        }
        else if (it_val_map->second->value == 1)
        {
            auto node_it = it_val_map->second;
            node_it->keys.erase(key);
            if (node_it->keys.empty() && node_it->value != 1)
            {
                value_key.erase(node_it);
            }
            val_map.erase(it_val_map);
        }
        else
        {
            auto node_it = it_val_map->second;
            auto prev_it = std::prev(node_it, 1);
            node_it->keys.erase(key);
            if (prev_it->value != node_it->value - 1)
            {
                // create one
                KvNode node;
                node.keys.insert(key);
                node.value = node_it->value - 1;
                val_map[key] = value_key.insert(node_it, node);
            }
            else
            {
                prev_it->keys.insert(key);
                val_map[key] = prev_it;
            }
            if (node_it->keys.empty() && node_it->value != 1)
            {
                value_key.erase(node_it);
            }
        }
    }
    /** Returns one of the keys with maximal value. */
    string getMaxKey() {
        auto it_max = std::prev(value_key.end(), 1);
        if (!it_max->keys.empty())
            return *(it_max->keys.begin());
        else
            return "";
    }
    /** Returns one of the keys with Minimal value. */
    string getMinKey() {
        auto it_min = value_key.begin();
        if (it_min->value == 1 && it_min->keys.empty())
            ++it_min;
        if (it_min != value_key.end() && !it_min->keys.empty())
            return *(it_min->keys.begin());
        else
            return "";
    }
};
/**
 * Your AllOne object will be instantiated and called as such:
 * AllOne obj = new AllOne();
 * obj.inc(key);
 * obj.dec(key);
 * string param_3 = obj.getMaxKey();
 * string param_4 = obj.getMinKey();
 */

 
 
 

Categories
木有技术

Linux Performance Observability Tools


Source(Crash Dump Analysis): http://d3s.mff.cuni.cz/teaching/crash_dump_analysis/slides/08-linux.pdf