一刷leetcode——数据结构

208. Implement Trie (Prefix Tree)

题意:构造Trie树的插入、查找操作

我的思路:字典树模板

我的代码:

class Trie {
public:
    vector<vector<int> > ch;
    vector<int> val;
    /** Initialize your data structure here. */
    Trie() {
        vector<int> root(26, 0);
        ch.push_back(root);
        val.push_back(0);
    }
    
    int idx(char c) { return c-'a'; }
    
    /** Inserts a word into the trie. */
    void insert(string word) {
        int u = 0, n = word.size(), c;
        for (int i = 0; i < n; i++) {
            c = idx(word[i]);
            if (!ch[u][c]) {
                vector<int> tmp(26, 0);
                ch[u][c] = ch.size();
                ch.push_back(tmp);
                val.push_back(0);
            }
            u = ch[u][c];
        }
        val[u] = 1;
    }
    
    /** Returns if the word is in the trie. */
    bool search(string word) {
        int u = 0, n = word.size(), c;
        for (int i = 0; i < n; i++) {
            c = idx(word[i]);
            if (!ch[u][c]) return 0;
            u = ch[u][c];
        }
        return val[u] > 0;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix) {
        int u = 0, n = prefix.size();
        for (int i = 0; i < n; i++) {
            int c = idx(prefix[i]);
            if (!ch[u][c]) return 0;
            u = ch[u][c];
        }
        return 1;
    }
};

/**
 * Your Trie object will be instantiated and called as such:
 * Trie obj = new Trie();
 * obj.insert(word);
 * bool param_2 = obj.search(word);
 * bool param_3 = obj.startsWith(prefix);
 */
View Code

211. Add and Search Word - Data structure design

题意:add函数插入单词形成词典,search函数查询有没有某单词,查询时“.”可以代表任何一个字母

我的思路:字典树+递归

我的代码:数组写法

class WordDictionary {
public:
    /** Initialize your data structure here. */
    int ch[40000][26], sz, val[40000];
    WordDictionary() {
        sz = 1;
        memset(ch[0], 0, sizeof(ch[0]));
    }
    
    /** Adds a word into the data structure. */
    void addWord(string word) {
        int u = 0, n = word.size();
        for (int i = 0; i < n; i++) {
            int c = word[i]-'a';
            if (!ch[u][c]) {
                memset(ch[sz], 0, sizeof(ch[sz]));
                val[sz] = 0;
                ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
        val[u] = 1;
    }
    
    /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
    bool query(int j, string word) {
        int n = word.size();
        for (int i = 0; i < n; i++) {
            if (word[i] != '.') {
                j = ch[j][word[i]-'a'];
                if (j == 0) return 0;
            } else {
                int flag = 1, k;
                for (k = 0; k < 26; k++) {
                    if (ch[j][k]) {
                        flag = 0;
                        if (query(ch[j][k], word.substr(i+1, n-1-i))) 
                            return 1;
                    }
                }
                if (flag || k == 26) return 0;
            }
        }
        if (val[j] == 1) return 1;
        return 0;
    }
    bool search(string word) {
        return query(0, word);
    }
};
View Code

solution解法:字典树指针写法

class TrieNode {
public:
    bool isKey;
    TrieNode* children[26];
    TrieNode(): isKey(false) {
        memset(children, NULL, sizeof(TrieNode*) * 26); 
    }
};

void addWord(string word) {
    TrieNode* run = root;
    for (char c : word) {
        if (!(run -> children[c - 'a']))
            run -> children[c - 'a'] = new TrieNode();
        run = run -> children[c - 'a']; 
    }
    run -> isKey = true;
}

private:
    TrieNode* root;

WordDictionary() {
    root = new TrieNode();
}

class TrieNode {
public:
    bool isKey;
    TrieNode* children[26];
    TrieNode(): isKey(false) {
        memset(children, NULL, sizeof(TrieNode*) * 26);
    }
};

class WordDictionary {
public:
    WordDictionary() {
        root = new TrieNode();
    }

    // Adds a word into the data structure.
    void addWord(string word) {
        TrieNode* run = root;
        for (char c : word) {
            if (!(run -> children[c - 'a'])) 
                run -> children[c - 'a'] = new TrieNode();
            run = run -> children[c - 'a'];
        }
        run -> isKey = true;
    }

    // Returns if the word is in the data structure. A word could
    // contain the dot character '.' to represent any one letter.
    bool search(string word) {
        return query(word.c_str(), root);
    }

private:
    TrieNode* root;

    bool query(const char* word, TrieNode* node) {
        TrieNode* run = node;
        for (int i = 0; word[i]; i++) {
            if (run && word[i] != '.')
                run = run -> children[word[i] - 'a'];
            else if (run && word[i] == '.') { 
                TrieNode* tmp = run;
                for (int j = 0; j < 26; j++) {
                    run = tmp -> children[j];
                    if (query(word + i + 1, run))
                        return true;
                }
            }
            else break;
        }
        return run && run -> isKey; 
    }
};
View Code

212. Word Search II

题意:给定一个字符棋盘和一个字典,输出棋盘上相邻字符连成的存在于字典中的单词

我的思路:Trie+dfs

我的代码:

class Solution {
public:
    vector<vector<int> > ch;
    vector<int> val;
    vector<string> ans;
    int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    
    int idx(char c) { return c-'a'; }
    void insert(string word) {
        int u = 0, n = word.size(), c;
        for (int i = 0; i < n; i++) {
            c = idx(word[i]);
            if (!ch[u][c]) {
                vector<int> tmp(26, 0);
                ch[u][c] = ch.size();
                ch.push_back(tmp);
                val.push_back(0);
            }
            u = ch[u][c];
        }
        val[u] = 1;
    }
    void dfs(vector<vector<char>>& board, int x, int y, int u, string tmp, vector<vector<bool>> flag) {
        flag[x][y] = 1;
        if (val[u] > 0 && find(ans.begin(), ans.end(), tmp) == ans.end()) ans.push_back(tmp);
        for (int i = 0; i < 4; i++) {
            int xx = x+dir[i][0], yy = y+dir[i][1];
            if (xx >= 0 && xx < board.size() && yy >= 0 && yy < board[0].size() && flag[xx][yy] == 0 && ch[u][board[xx][yy]-'a'])
                dfs(board, xx, yy, ch[u][board[xx][yy]-'a'], tmp+board[xx][yy], flag);
        }
    }
    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        int m = board.size(), n = board[0].size();
        vector<int> root(26, 0);
        ch.push_back(root);
        val.push_back(0);
        for (int i = 0; i < words.size(); i++) insert(words[i]);
        vector<vector<bool> > flag(m, vector<bool>(n, 0));
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
                if (ch[0][board[i][j]-'a']) {
                    string tmp;
                    dfs(board, i, j, ch[0][board[i][j]-'a'], tmp+board[i][j], flag);
                }
        return ans;
    }
};
View Code

214. Shortest Palindrome

题意:输出给定字符串前边加上最少的字符变成的回文串

我的思路:问题可以转化为求最长的回文前缀长度,因为在前边加上剩下的倒序即可、

    最长回文前缀长度:将原字符串翻转以后加在原字符串的后面(中间需要加一个其他字符),前缀与后缀最大相同长度(KMP)即是

我的代码:

class Solution {
public:
    string shortestPalindrome(string s) {
        if (s.size() == 0) return s;
        string ss = s, ans = s;
        reverse(ss.begin(), ss.end());
        s = s+'#'+ss;
        int n = s.size(), i = 0, j = -1, m = ss.size();
        vector<int> next(n+1, -1);
        while (s[i]) {
            if (j == -1 || s[i] == s[j]) {
                i++, j++;
                next[i] = j;
            } else
                j = next[j];
        }
        ss = ss.substr(0, m-next[n]);
        return ss+ans;
    }
};
View Code

218. The Skyline Problem

题意:给出一些矩形,求出这些矩形构成的轮廓线,返回轮廓线上每条水平线左边点的坐标集合。

我的思路:线段树区间修改求最大,离散化,最后逐个节点查询高度值,高度改变压入结果

我的代码:

const int maxn = 20005;
class Solution {
public:
    unordered_map<int, int> mp, mp_re;
    struct node
    {
        int l, r, mx; //mx既是最大,也充当lazy标记
    }p[4*maxn];
    void build(int l, int r, int i) {
        p[i].l = l;
        p[i].r = r;
        p[i].mx = 0;
        if (l == r) return;
        int mid = (l+r)>>1;
        build(l, mid, i<<1);
        build(mid+1, r, i<<1|1);
    }
    void insert(int l, int r, int i, int h) {
        if (p[i].mx >= h) return;
        if (p[i].l >= l && p[i].r <= r) {
            p[i].mx = h;
            return;
        }
        if (p[i].mx) {
            p[i<<1].mx = max(p[i].mx, p[i<<1].mx);
            p[i<<1|1].mx = max(p[i].mx, p[i<<1|1].mx);
            p[i].mx = 0;
        }
        int mid = (p[i].l + p[i].r)>>1;
        if(l <= mid) insert(l, r, i<<1, h);
        if(mid < r) insert(l, r, i<<1|1, h);
    }
    void query(vector<pair<int, int>> &ans, int i) {
        if (p[i].l == p[i].r) {
            if (!ans.empty() && p[i].mx == ans[ans.size()-1].second) return;
            ans.push_back(make_pair(mp_re[p[i].l], p[i].mx));
            return;
        }
        if (p[i].mx) {
            p[i<<1].mx = max(p[i].mx, p[i<<1].mx);
            p[i<<1|1].mx = max(p[i].mx, p[i<<1|1].mx);
            p[i].mx = 0;
        }
        query(ans, i<<1);
        query(ans, i<<1|1);
    }
    vector<pair<int, int>> getSkyline(vector<vector<int>>& buildings) {
        vector<int> idx;
        vector<pair<int, int>> ans;
        if (buildings.size() == 0) return ans;
        for (int i = 0; i < buildings.size(); i++)
            for (int j = 0; j < 2; j++)
                if (mp.find(buildings[i][j]) == mp.end()) {
                    mp[buildings[i][j]] = 1;
                    idx.push_back(buildings[i][j]);
                }
        sort(idx.begin(), idx.end());
        for (int i = 0; i < idx.size(); i++) {
            mp[idx[i]] = i+1;
            mp_re[i+1] = idx[i];
        }
        build(1, idx.size() ,1);
        for (int i = 0; i < buildings.size(); i++)
            insert(mp[buildings[i][0]], mp[buildings[i][1]]-1, 1, buildings[i][2]);
        query(ans, 1);
        return ans;
    }
};
View Code

solution解法:优先队列,http://blog.csdn.net/u012501459/article/details/47271561

class Solution {
public:
    vector<pair<int, int>> getSkyline(vector<vector<int>>& buildings) {
        vector<pair<int, int>> ans;
        int cur = 0, cur_x, cur_h = -1, l = buildings.size();
        priority_queue<pair<int, int>> live;  //前边是高度,后边是结束点坐标
        while (cur < l || !live.empty()) {
            cur_x = live.empty() ? buildings[cur][0] : live.top().second;  //最高建筑结束点
            if (cur >= l || buildings[cur][0] > cur_x)
                while (!live.empty() && (live.top().second <= cur_x))
                    live.pop();   //将结束时间小于等于最高建筑结束点的建筑物从优先队列中弹出
            else {   //如果当前遍历到的建筑物在最高的建筑物结束之前开始,那么处理当前的建筑物
                cur_x = buildings[cur][0];
                while (cur < l && buildings[cur][0] == cur_x) {   //所有在同一点开始的建筑
                    live.push(make_pair(buildings[cur][2], buildings[cur][1]));
                    cur++;
                }
            }
            cur_h = live.empty() ? 0 : live.top().first;
            if (ans.empty() || ans.back().second != cur_h)
                ans.push_back(make_pair(cur_x, cur_h));
        }
        return ans;
    }
};
View Code

224. Basic Calculator

题意:给定字符串表示有括号加减法,输出结果

我的思路:栈

我的代码:

class Solution {
public:
    int calculate(string s) {
        s += '.';
        stack<int> nums, oper;
        int num = 0, fuhao = 1, ans = 0;
        for (int i = 0; i < s.size(); i++) {
            if (isdigit(s[i])) {
                num = num*10+s[i]-'0';
            } else {
                if (s[i] == ' ') continue;
                ans += fuhao*num;
                num = 0;
                if (s[i] == '+') fuhao = 1;
                else if (s[i] == '-') fuhao = -1;
                else if (s[i] == '(') {
                    nums.push(ans);     ans = 0;
                    oper.push(fuhao);   fuhao = 1;
                } else if (s[i] == ')') {
                    ans = ans*oper.top()+nums.top();
                    nums.pop();
                    oper.pop();
                }
            }
        }
        return ans;
    }
};
View Code

 225. Implement Stack using Queues

题意:队列实现栈

我的思路:两个队列

我的代码:

class MyStack {
public:
    queue<int> q[2];
    int flag;
    /** Initialize your data structure here. */
    MyStack() {
        flag = 0; ///初始化0进1出
    }
    
    /** Push element x onto stack. */
    void push(int x) {
        q[flag].push(x);
    }
    
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        int n = q[flag].size();
        for (int i = 0; i < n-1; i++) {
            q[flag^1].push(q[flag].front());
            q[flag].pop();
        }
        int ans = q[flag].front();
        q[flag].pop();
        flag ^= 1;
        return ans;
    }
    
    /** Get the top element. */
    int top() {
        int n = q[flag].size();
        for (int i = 0; i < n-1; i++) {
            q[flag^1].push(q[flag].front());
            q[flag].pop();
        }
        int ans = q[flag].front();
        q[flag^1].push(ans);
        q[flag].pop();
        flag ^= 1;
        return ans;
    }
    
    /** Returns whether the stack is empty. */
    bool empty() {
        return q[flag].empty();
    }
};
View Code

solution:一个队列就可以。。

class MyStack {
public:
    /** Initialize your data structure here. */
    int size;
    queue<int> q;
    MyStack() {
        size = 0;
    }
    
    /** Push element x onto stack. */
    void push(int x) {
        q.push(x);
        size++;
    }
    
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        int t = q.back();
        while(q.front() != t){                                          
            q.push(q.front());
            q.pop();
        }
        q.pop();
        size--;
        return t;
    }
    
    /** Get the top element. */
    int top() {
        return q.back();
    }
    
    /** Returns whether the stack is empty. */
    bool empty() {
        return size == 0;
    }
};

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack obj = new MyStack();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.top();
 * bool param_4 = obj.empty();
 */
View Code

227. Basic Calculator II

题意:计算器,加减乘除

我的思路:加:原数压栈;减:相反数压栈;乘:取出一个数相乘压栈;除:取出一个数相除压栈,最后栈里数字相加

我的代码:

class Solution {
public:
    int calculate(string s) {
        s += '.';
        stack<int> sk;
        int num = 0, fuhao = 1, a;
        for (int i = 0; i < s.size(); i++) {
            if (isdigit(s[i])) {
                num = num*10+s[i]-'0';
            } else {
                if (s[i] == ' ') continue;
                switch (fuhao) {
                    case 1: 
                        sk.push(num);
                        break;
                    case 2: 
                        sk.push(-num);
                        break;
                    case 3:
                        a = sk.top();
                        sk.pop();
                        sk.push(a*num);
                        break;
                    case 4:
                        a = sk.top();
                        sk.pop();
                        sk.push(a/num);
                        break;
                }
                switch (s[i]) {
                    case '+': fuhao = 1; break;
                    case '-': fuhao = 2; break;
                    case '*': fuhao = 3; break;
                    case '/': fuhao = 4; break;
                }
                num = 0;
            }
        }
        int ans = 0;
        while (!sk.empty()) {
            ans += sk.top();
            sk.pop();
        }
        return ans;
    }
};
View Code

232. Implement Queue using Stacks

题意:用队列实现栈

我的sl:水题

我的代码:

class MyQueue {
public:
    stack<int> s;
    /** Initialize your data structure here. */
    MyQueue() {
        
    }
    
    /** Push element x to the back of queue. */
    void push(int x) {
        s.push(x);
    }
    
    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        int n = s.size();
        stack<int> tmp;
        for (int i = 0; i < n-1; i++) {
            tmp.push(s.top());
            s.pop();
        }
        int ans = s.top();
        s.pop();
        for (int i = 0; i < n-1; i++) {
            s.push(tmp.top());
            tmp.pop();
        }
        return ans;
    }
    
    /** Get the front element. */
    int peek() {
        int n = s.size();
        stack<int> tmp;
        for (int i = 0; i < n-1; i++) {
            tmp.push(s.top());
            s.pop();
        }
        int ans = s.top();
        tmp.push(ans);
        s.pop();
        for (int i = 0; i < n; i++) {
            s.push(tmp.top());
            tmp.pop();
        }
        return ans;
    }
    
    /** Returns whether the queue is empty. */
    bool empty() {
        return s.empty();
    }
};
View Code

solution写法:

class Queue {
    stack<int> input, output;
public:

    void push(int x) {
        input.push(x);
    }

    void pop(void) {
        peek();
        output.pop();
    }

    int peek(void) {
        if (output.empty())
            while (input.size())
                output.push(input.top()), input.pop();
        return output.top();
    }

    bool empty(void) {
        return input.empty() && output.empty();
    }
};
View Code

239. Sliding Window Maximum

题意:输出一个数组给定窗口长度移动的最大值

solution解法:双向队列deque(单调队列)

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

257. Binary Tree Paths

题意:以字符串形式输出二叉搜索树的所有路径

我的思路:dfs,to_string

我的代码:

class Solution {
public:
    void dfs(TreeNode* root, vector<string> &ans, string tmp) {
        if (root->left == NULL && root->right == NULL) {
            ans.push_back(tmp);
            return;
        }
        if (root->left) dfs(root->left, ans, tmp+"->"+to_string(root->left->val));
        if (root->right) dfs(root->right, ans, tmp+"->"+to_string(root->right->val));
    }
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> ans;
        if (root == NULL) return ans;
        string tmp;
        tmp = to_string(root->val);
        dfs(root, ans, tmp);
        return ans;
    }
};
View Code

九章最优解:

class Solution {
public:
    /**
     * @param root the root of the binary tree
     * @return all root-to-leaf paths
     */
    vector<string> binaryTreePaths(TreeNode* root) {
        // Write your code here
        vector<string> path;
        if(root == NULL)
            return path;
        vector<vector<int> > pathv;    
        unordered_map<TreeNode*, bool> visited;
        stack<TreeNode*> stk;
        stk.push(root);
        visited[root] = true;
        if(root->left == NULL && root->right == NULL)
            save(pathv, stk);
        while(!stk.empty())
        {
            TreeNode* top = stk.top();
            if(top->left && visited[top->left] == false)
            {
                stk.push(top->left);
                visited[top->left] = true;
                if(top->left->left == NULL && top->left->right == NULL)
                    save(pathv, stk);
                continue;
            }
            if(top->right && visited[top->right] == false)
            {
                stk.push(top->right);
                visited[top->right] = true;
                if(top->right->left == NULL && top->right->right == NULL)
                    save(pathv, stk);
                continue;
            }
            stk.pop();
        }
        return convert(pathv);
    }

    void save(vector<vector<int> >& pathv, stack<TreeNode*> stk)
    {
        vector<int> cur;
        while(!stk.empty())
        {
            TreeNode* top = stk.top();
            cur.push_back(top->val);
            stk.pop();
        }
        reverse(cur.begin(), cur.end());
        pathv.push_back(cur);
    }

    vector<string> convert(vector<vector<int> >& pathv)
    {
        vector<string> path;
        for(int i = 0; i < pathv.size(); i ++)
        {
            string cur;
            cur += to_string(pathv[i][0]);
            for(int j = 1; j < pathv[i].size(); j ++)
            {
                cur += "->";
                cur += to_string(pathv[i][j]);
            }
            path.push_back(cur);
        }
        return path;
    }
};
View Code

307. Range Sum Query - Mutable

题意:区间和查询,点修改

我的思路:线段树

我的代码:繁琐了

class NumArray {
public:
    struct Node {
        int l, r, sum;
    };
    vector<Node> p;
    vector<int> num;
    void build(int l, int r, int i) {
        p[i].l = l;
        p[i].r = r;
        if (l == r) {
            p[i].sum = num[l];
            return;
        }
        int mid = (l+r)/2;
        build(l, mid, i<<1);
        build(mid+1, r, i<<1|1);
        p[i].sum = p[i<<1].sum+p[i<<1|1].sum;
    }
    NumArray(vector<int> nums) {
        int n = nums.size();
        if (n > 0) {
            num = nums;
            p.resize(n<<2);
            build(0, n-1, 1);
        }
    }
    
    void upd(int k, int add, int i) {
        if (p[i].l == p[i].r) {
            p[i].sum += add;
            return;
        }
        int mid = (p[i].l+p[i].r)>>1;
        if (k <= mid) upd(k, add, i<<1);
        else upd(k, add, i<<1|1);
        p[i].sum = p[i<<1].sum+p[i<<1|1].sum;
    }
    void update(int i, int val) {
        upd(i, val-num[i], 1);
        num[i] = val;
    }
    
    int query(int l, int r, int i)
    {
        if(l == p[i].l && p[i].r == r) return p[i].sum;
        int mid = (p[i].l+p[i].r)>>1;
        if (r<=mid) return query(l, r, i<<1);
        else if (l>mid) return query(l, r, (i<<1)+1);
        else return query(l, mid, i<<1)+query(mid+1, r, (i<<1)+1);
    }
    int sumRange(int i, int j) {
        return query(i, j, 1);
    }
};
View Code

solution解法:树状数组

class NumArray {
public:
    NumArray(vector<int> nums) {
        int n = nums.size();
        this->nums = bit = vector<int>(n + 1);
        for (int i = 0; i < n; i++) update(i, nums[i]);
    }
    void update(int i, int val) {
        for (int j = i + 1; j < nums.size(); j += j & -j) bit[j] += val - nums[i + 1];
        nums[i + 1] = val;
    }
    int sumRange(int i, int j) {
        return sum(j + 1) - sum(i);
    }
private:
    vector<int> nums, bit;
    int sum(int i) {
        int res = 0;
        for (; i > 0; i -= i & -i) res += bit[i];
        return res;
    }
};
View Code

331. Verify Preorder Serialization of a Binary Tree

题意:判断一个序列是否可以是一个二叉树的前序遍历

我的思路:连续遇到两个“#”,说明这是叶子节点,删去他们及他们的根节点,用一个’#‘代替,直到最后剩一个’#‘说明是二叉树。否则,返回false。

我的代码:

class Solution {
public:
    bool isValidSerialization(string preorder) {
        stack<char> s;
        int num = 0;
        for (int i = 0; i < preorder.size(); i++) {
            if (isdigit(preorder[i])) {
                while (isdigit(preorder[i])) {
                    num = num*10+preorder[i]-'0';
                    i++;
                }
                s.push(num);
                num = 0;
            } else if (preorder[i] == '#') {
                while (!s.empty() && s.top() == '#') {
                    s.pop();
                    if (!s.empty() && s.top() != '#') s.pop();
                    else return 0;
                }
                s.push(preorder[i]);
            }
        }
        return s.size() == 1 && s.top() == '#';
    }
};
View Code

disscuss解法:通过出度、入度之差计算,如果是二叉树,那么在整个过程中差值为非负且最后为0

public boolean isValidSerialization(String preorder) {
    String[] nodes = preorder.split(",");
    int diff = 1;
    for (String node: nodes) {
        if (--diff < 0) return false;
        if (!node.equals("#")) diff += 2;
    }
    return diff == 0;
}
View Code

347. Top K Frequent Elements

题意:给定一个数组,输出数组中出现频率前k位的数字

我的思路:统计各个数字的出现次数,map表示数字与次数数组的映射,优先队列排出前k位

我的代码:

class Solution {
public:
    struct Item {
        int num, cnt;
        bool operator < (const  Item& a) const {
            return cnt < a.cnt;
        }
    };
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map <int, int> hash;
        int n = nums.size();
        vector<Item> item;
        for (int i = 0; i < n; i++) {
            if (hash.find(nums[i]) != hash.end()) item[hash[nums[i]]].cnt++;
            else {
                Item tmp;
                tmp.num = nums[i];
                tmp.cnt = 1;
                item.push_back(tmp);
                hash[nums[i]] =  item.size()-1;
            }
        }
        priority_queue<Item> pq;
        vector<int> ans;
        for (int i = 0; i < item.size(); i++) pq.push(item[i]);
        while (k--) {
            Item tmp = pq.top();
            pq.pop();
            ans.push_back(tmp.num);
        }
        return ans;
    }
};
View Code

九章最优解:

public class Solution {
    public List<Integer> topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> hashmap = new HashMap<Integer, Integer>();
        PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<Map.Entry<Integer, Integer>>(
            new Comparator<Map.Entry<Integer, Integer>>() {
                public int compare(Map.Entry<Integer, Integer> e1, Map.Entry<Integer, Integer> e2) {
                    return e1.getValue() - e2.getValue();
                }
            });
        for (int i = 0; i < nums.length; i++) {
            if (!hashmap.containsKey(nums[i])) {
                hashmap.put(nums[i], 1);
            } else {
                hashmap.put(nums[i], hashmap.get(nums[i]) + 1);
            }
        }
        
        for (Map.Entry<Integer, Integer> entry : hashmap.entrySet()) {
            if (queue.size() < k) {
                queue.offer(entry);
            } else if (queue.peek().getValue() < entry.getValue()) {
                queue.poll();
                queue.offer(entry);
            }
        }
        
        List<Integer> ans = new ArrayList<Integer>();
        for (Map.Entry<Integer, Integer> entry : queue)
            ans.add(entry.getKey());
        return ans;
    }
}
View Code

352. Data Stream as Disjoint Intervals

题意:将数据流表示成区间形式

我的思路:数据流插入排序,再表示成区间,O(n)

我的代码:

class SummaryRanges {
public:
    vector<int> num;
    /** Initialize your data structure here. */
    SummaryRanges() {
        
    }
    
    void addNum(int val) {
        int i = 0;
        while (i < num.size() && num[i] < val) i++;
        num.insert(num.begin()+i, val);
    }
    
    vector<Interval> getIntervals() {
        vector<Interval> ans;
        int flag = 0, i = 0;
        Interval tmp;
        while (i < num.size()) {
            if (flag) {
                while (num[i] == num[i-1] || num[i] == num[i-1]+1) i++;
                tmp.end = num[i-1];
                ans.push_back(tmp);
                flag = 0;
            } else {
                tmp.start = num[i++];
                flag = 1;
            }
        }
        if (flag) {
            tmp.end = num[i-1];
            ans.push_back(tmp);
        }
        return ans;
    }
};
View Code

discuss解法:用一个数组来保存结果, 然后每次搜索的时候用lower_bound可以找到第一个大于等于要插入的值的区间, 当前要插入的值可能会正好等于上个区间的end+1, 因此需要做个判断. 把能合并的区间都从数组中删除, 最后插入一个新的区间.set二叉搜索树插入查找都可以在O(log n)完成, 只需要在返回结果的时候将set中的值放到vector中即可.

class SummaryRanges {
public:
    /** Initialize your data structure here. */
    void addNum(int val) {
        auto it = st.lower_bound(Interval(val, val));
        int start = val, end = val;
        if(it != st.begin() && (--it)->end+1 < val) it++;
        while(it != st.end() && val+1 >= it->start && val-1 <= it->end)
        {
            start = min(start, it->start);
            end = max(end, it->end);
            it = st.erase(it);
        }
        st.insert(it,Interval(start, end));
    }
    
    vector<Interval> getIntervals() {
        vector<Interval> result;
        for(auto val: st) result.push_back(val);
        return result;
    }
private:
    struct Cmp{
        bool operator()(Interval a, Interval b){ return a.start < b.start; }
    };
    set<Interval, Cmp> st;
};
View Code

378. Kth Smallest Element in a Sorted Matrix

题意:输出一个矩阵中第k小的数

我的思路:优先队列

我的代码:

class Solution {
public:
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        priority_queue<int> pq;
        for (int i = 0; i < matrix.size(); i++)
            for (int j = 0; j < matrix[0].size(); j++)
                pq.push(matrix[i][j]);
        k = matrix.size()*matrix[0].size()+1-k;
        while (k > 1) pq.pop(), k--;
        return pq.top();
    }
};
View Code

九章最优解:无

404. Sum of Left Leaves

题意:求所有左叶子节点之和

我的思路:递归

class Solution {
public:
    int ans;
    void dfs(TreeNode* root, bool flag) {
        if (root->left == NULL && root->right == NULL && flag) ans += root->val; 
        if (root->left) dfs(root->left, 1);
        if (root->right) dfs(root->right, 0);
    }
    int sumOfLeftLeaves(TreeNode* root) {
        if (root) dfs(root, 0);
        return ans;
    }
};
View Code

solution解法:也是递归,但是写的好一些

class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        if(!root)
            return 0;
        if(root->left && !root->left->left && !root->left->right)
            return root->left->val + sumOfLeftLeaves(root->right);
        
        return sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
    }
};
View Code

407. Trapping Rain Water II

题意:给定一个二维矩阵,数值表示高度,求存水量

我的思路:优先队列,先将边缘入列,从高度小的开始取,bfs将它周围还没到过的地方入列,ans += max(0, tmp.h-heightMap[x][y]);

我的代码:

class Solution {
public:
    vector<vector<int>> dir = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    struct cell {
        int r, c, h;
        cell(int i, int j, int k) {
            r = i; c = j; h = k;
        }
        bool operator < (const cell& a) const {
            return h > a.h;
        }
    };
    int trapRainWater(vector<vector<int>>& heightMap) {
        if (heightMap.size() == 0) return 0;
        priority_queue<cell> pq;
        int m = heightMap.size(), n = heightMap[0].size();
        vector<vector<bool>> v(m, vector<bool>(n, 0));
        for (int i = 0 ; i< m; i++) {
            cell tmp1(i, 0, heightMap[i][0]), tmp2(i, n-1, heightMap[i][n-1]);
            pq.push(tmp1);
            pq.push(tmp2);
            v[i][0] = 1; v[i][n-1] = 1;
        }
        for (int i = 1; i < n-1; i++) {
            cell tmp1(0, i, heightMap[0][i]), tmp2(m-1, i, heightMap[m-1][i]);
            pq.push(tmp1);
            pq.push(tmp2);
            v[0][i] = 1; v[m-1][i] = 1;
        }
        int ans = 0;
        while (!pq.empty()) {
            cell tmp = pq.top();
            pq.pop();
            for (int i = 0; i < 4; i++) {
                int x = tmp.r+dir[i][0], y = tmp.c+dir[i][1];
                if (x >= 0 && x < m && y >= 0 && y < n && !v[x][y]) {
                    v[x][y] = 1;
                    cell g(x, y, max(heightMap[x][y], tmp.h));
                    pq.push(g);
                    ans += max(0, tmp.h-heightMap[x][y]);
                }
            }
        }
        return ans;
    }
};
View Code

451. Sort Characters By Frequency

题意:将数组中的字符按频率由大到小输出

我的思路:hash+优先队列

我的代码:

class Solution {
public:
    struct Item {
        int cnt = 0;
        char c;
        bool operator < (const  Item& a) const {
            return cnt < a.cnt;
        }
    };
    string frequencySort(string s) {
        priority_queue<Item> pq;
        vector<Item> hehe(128);
        string ans;
        for (int i = 0; i < s.size(); i++) {
            hehe[s[i]].c = s[i];
            hehe[s[i]].cnt++;
        }
        for (int i = 0; i < 128; i++) pq.push(hehe[i]);
        while (pq.top().cnt > 0) {
            Item a = pq.top();
            while (a.cnt--) ans += a.c;
            pq.pop();
        }
        return ans;
    }
};
View Code

solution解法:思路一样的,写的好一点

class Solution {
public:
    string frequencySort(string s) {
        string ret;
        vector<int> cnt(256, 0);
        for (auto& ch : s) {
            cnt[ch]++;
        }
        priority_queue<pair<int, int>> pq;
        for (int i = 0; i < cnt.size(); i++) {
            if (cnt[i] != 0) {
                pq.push({cnt[i], i});
            }
        }
        while (!pq.empty()) {
            ret += string(pq.top().first, pq.top().second);
            pq.pop();
        }
        return ret;
    }
};
View Code

493. Reverse Pairs

题意:找出数组中i < j and nums[i] > 2*nums[j]的对数

我的思路:

1)归并排序

class Solution {
public:
    void merge(vector<int>& nums, int l, int m, int r, int& ans) {
        vector<int> tmp;
        int i = l, j = m+1, p = m+1;
        while (i <= m) {
            while (p <= r && nums[i] > 2L*nums[p]) p++;
            ans += p-m-1;
            while (j <= r && nums[i] >= nums[j]) tmp.push_back(nums[j++]);
            tmp.push_back(nums[i++]);
        }
        while (j <= r) tmp.push_back(nums[j++]);
        for(i = l; i <= r; i++) nums[i] = tmp[i-l];
    }
    void mergesort(vector<int>& nums, int l, int r, int& ans) {
        if (l < r) {
            int mid = l+(r-l)/2;
            mergesort(nums, l, mid, ans);
            mergesort(nums, mid+1, r, ans);
            merge(nums, l, mid, r, ans);
        }
    }
    int reversePairs(vector<int>& nums) {
        int ans = 0;
        mergesort(nums, 0, nums.size()-1, ans);
        return ans;
    }
};
View Code

 

496. Next Greater Element I

题意:数组1是数组2的子集,找出1中的元素在2中的位置以后比他大的第一个数

我的思路:map记录数字在1中的位置,栈找2的上升沿

我的代码:

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums) {
        vector<int> ans(findNums.size(), -1);
        unordered_map<int, int> m;
        stack<int> s;
        for (int i = 0; i < findNums.size(); i++) m[findNums[i]] = i;
        for (int i = 0; i < nums.size(); i++) {
            while (!s.empty() && s.top() < nums[i]) {
                if (m.find(s.top()) != m.end()) ans[m[s.top()]] = nums[i];
                s.pop();
            }
            s.push(nums[i]);
        }
        return ans;
    }
};
View Code

547. Friend Circles

题意:给定同学间的认识关系,问有多少个小团体

我的思路:并查集

我的代码:

class Solution {
public:
    int find(int x, vector<int> &pre) {
        int cur = x, tmp;
        while (pre[x] != x) x = pre[x];
        while (cur != x) {
            tmp = pre[cur];
            pre[cur] = x;
            cur = tmp;
        }
        return x;
    }
    void get(int x, int y, vector<int> &pre) {
        int fx = find(x, pre), fy = find(y, pre);
        if (fx != fy) pre[fy] = fx;
    }
    int findCircleNum(vector<vector<int>>& M) {
        int n = M.size(), sum = 0;
        vector<int> pre(n), flag(n, 0);
        for (int i = 0; i < n; i++) pre[i] = i;
        for (int i = 0; i < n; i++)
            for (int j = i+1; j < n; j++)
                if (M[i][j]) get(i, j, pre);
        for (int i = 0; i < n; i++) {
            int k = find(i, pre);
            if (flag[k] == 0) {
                sum++;
                flag[k] = 1;
            }
        }
        return sum;
    }
};
View Code

632. Smallest Range

题意:给定k个有序数组,找出最小的区间使得每个数组在此区间里都有数字

我的思路:优先队列,类似于将k个有序数组合并,每次弹出最小的数字后,加入他所在的数组的下一个数字,维护最小的区间

我的代码:

class Solution {
public:
    struct Item {
        int val, i, j;
        bool operator < (const  Item& a) const {
            return val > a.val;
        }
    };
    vector<int> smallestRange(vector<vector<int>>& nums) {
        priority_queue<Item> pq;
        int maxn = 0x80000000, range = 0x7fffffff, s, e;
        for (int i = 0; i < nums.size(); i++) {
            Item item;
            maxn = max(maxn, nums[i][0]);
            item.val = nums[i][0];
            item.i = i;
            item.j = 0;
            pq.push(item);
        }
        while (1) {
            Item tmp = pq.top();
            pq.pop();
            if (maxn-tmp.val < range) {
                range = maxn-tmp.val;
                s = tmp.val;
                e = maxn;
            }
            if (tmp.j < nums[tmp.i].size()-1) {
                Item item;
                maxn = max(maxn, nums[tmp.i][tmp.j+1]);
                item.val = nums[tmp.i][tmp.j+1];
                item.i = tmp.i;
                item.j = tmp.j+1;
                pq.push(item);
            } else
                break;
        }
        return {s, e};
    }
};
View Code

648. Replace Words

题意:将句子中的单词用他的前缀代替,前缀给定

我的思路:字典树

我的代码:

class Solution {
public:
    class Trie {
    public:
        vector<vector<int> > ch;
        vector<int> val;
        Trie() {
            vector<int> root(26, 0);
            ch.push_back(root);
            val.push_back(0);
        }
        int idx(char c) { return c-'a'; }
        void insert(string word) {
            int u = 0, n = word.size(), c;
            for (int i = 0; i < n; i++) {
                c = idx(word[i]);
                if (!ch[u][c]) {
                    vector<int> tmp(26, 0);
                    ch[u][c] = ch.size();
                    ch.push_back(tmp);
                    val.push_back(0);
                }
                u = ch[u][c];
            }
            val[u] = 1;
        }
        string search(string word) {
            int u = 0, n = word.size(), c;
            string tmp;
            for (int i = 0; i < n; i++) {
                c = idx(word[i]);
                tmp += word[i];
                if (!ch[u][c]) return word;
                u = ch[u][c];
                if (val[u] > 0) return tmp;
            }
            return word;
        }
    };
    string replaceWords(vector<string>& dict, string sentence) {
        Trie T;
        for (int i = 0; i < dict.size(); i++) T.insert(dict[i]);
        string ans;
        int i = 0, j = 0;
        while (j < sentence.length()) {
            if (sentence[j] == ' ') {
                ans = ans+T.search(sentence.substr(i, j-i))+' ';
                i = j+1;
            }
            j++;
        }
        ans = ans+T.search(sentence.substr(i, j-i));
        return ans;
    }
};
View Code

684. Redundant Connection

题意:找出无向图中的唯一一条 重边

我的思路:并查集

我的代码:

class Solution {
public:
    int find(int x, vector<int>& pre)
    {
        int root=x;
        while(pre[root]!=root) root=pre[root];
        return root;
    }
    vector<int> findRedundantConnection(vector<vector<int>>& edges) {
        int n = edges.size();
        vector<int> pre(n+1);
        for (int i = 0; i <= n; i++) pre[i] = i;
        for (int i = 0; i < n; i++) {
            int x = find(edges[i][0], pre), y = find(edges[i][1], pre);
            if (x == y) return edges[i];
            pre[x] = y;
        }
    }
};
View Code

 

转载于:https://www.cnblogs.com/hqxue/p/6953501.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值