石器时代 —— Leetcode刷题日记(精选算法200题)

文章目录

  • 156. 上下翻转二叉树
    • 递归法
    • 迭代
  • 157. 用 Read4 读取 N 个字符
  • 158. 用 Read4 读取 N 个字符 II
  • 159. 至多包含两个不同字符的最长子串
  • 161. 相隔为 1 的编辑距离
  • 163. 缺失的区间
  • 186. 翻转字符串里的单词 II
  • 243. 最短单词距离
  • 244. 最短单词距离 II
  • 245. 最短单词距离 III
  • 250. 统计同值子树
  • 255. 验证前序遍历序列二叉搜索树

156. 上下翻转二叉树

  • 有二叉树:其中所有的右节点要么是具有兄弟节点(拥有相同父节点的左节点)的叶节点,要么为空
  • 要求完成操作,类似如下:
    石器时代 —— Leetcode刷题日记(精选算法200题)_第1张图片

递归法

class Solution {
public:
    TreeNode* upsideDownBinaryTree(TreeNode* root) {
        TreeNode* head = NULL;
        helper(root, head);
        return head;
    }
    void helper(TreeNode* node, TreeNode*& head) {
        if (!node) return;
        helper(node->left, head);
        helper(node->right, head);
        if (!head && !node->left) head = node;
        if (node->left) {
            node->left->left = node->right;
            node->left->right = node;
            node->left = NULL; // 避免形成环
            node->right = NULL;
        }
    }
};

迭代

class Solution {
public:
    TreeNode* upsideDownBinaryTree(TreeNode* root) {
        if (!root) return NULL;
        stack<TreeNode*> st; 
        st.push(root);
        TreeNode *node = root, *head = NULL;
        while (node->left) {
            node = node->left;
            st.push(node);
        }
        head = st.top(); node = st.top();
        st.pop();
        while (!st.empty()) {
            TreeNode* tmp = st.top(); st.pop();
            node->left = tmp->right;
            node->right = tmp;
            tmp->right = NULL;
            tmp->left = NULL;
            node = tmp;
        }
        return head;
    }
};

157. 用 Read4 读取 N 个字符

  • read4最多读取4个字符
class Solution {
public:
    /**
     * @param buf Destination buffer
     * @param n   Number of characters to read
     * @return    The number of actual characters read
     */
    int read(char *buf, int n) {
        char* temp = new char[4];
        int ans = 0;
        int buf_len = 0;
        while(true){
            int cnt = read4(temp);
            for(int i = 0;i<cnt;i++){
                if(buf_len >= n)
                    break;
                buf[buf_len] = temp[i];
                buf_len++;
            }
            if(cnt == 0 || buf_len >= n)
                break;
        }
        return buf_len;
    }
};

158. 用 Read4 读取 N 个字符 II

  • TODO

159. 至多包含两个不同字符的最长子串

class Solution {
public:
    int lengthOfLongestSubstringTwoDistinct(string s) {
        unordered_map<char, int> m;
        int left = 0, right = 0;
        int res = 0;
        while (right < s.size()) {
            m[s[right]]++;
            right++;
            while (m.size() > 2) {
                if (m.count(s[left])!=0) {
                    if (m[s[left]] > 0) m[s[left]]--;
                    if (m[s[left]] == 0) m.erase(s[left]);
                }
                left++;
            }
            res = max(res, right - left);
        }
        return res;
    }
};

161. 相隔为 1 的编辑距离

满足编辑距离等于 1 有三种可能的情形:
往 s 中插入一个字符得到 t
从 s 中删除一个字符得到 t
在 s 中替换一个字符得到 t

class Solution {
public:
    bool isOneEditDistance(string s, string t) {
        if (s.size() > t.size()) swap(s, t);
        int sn = s.size(), tn = t.size();
        if (tn - sn > 1) return false;
        for (int i = 0; i < sn; i++) {
            if (s[i] != t[i]) {
                if (sn == tn) return s.substr(i+1) == t.substr(i+1);
                else return s.substr(i) == t.substr(i+1);
            }
        }
        return sn + 1 == tn;
    }
};

163. 缺失的区间

输入: nums = [0, 1, 3, 50, 75], lower = 0 和 upper = 99,
输出: [“2”, “4->49”, “51->74”, “76->99”]

class Solution {
public:
    vector<string> findMissingRanges(vector<int>& nums, int lower, int upper) {
        vector<string> res;
        if (nums.empty()) {
            oneAppend(res, (long int)lower-1, (long int)upper+1);
            return res;
        }
        oneAppend(res, (long int)lower-1, nums.front());
        for (int i = 1; i < nums.size(); i++)
            oneAppend(res, nums[i-1], nums[i]);
        oneAppend(res, nums.back(), (long int)upper+1);
        return res;
    }
    void oneAppend(vector<string>& res, long int L, long int R) {
        if (R - L == 2) 
            res.push_back(to_string(L+1));
        if (R - L > 2)
            res.push_back(to_string(L+1)+"->"+to_string(R-1)); 
    }
};

186. 翻转字符串里的单词 II

输入: [“t”,“h”,“e”," “,“s”,“k”,“y”,” “,“i”,“s”,” “,“b”,“l”,“u”,“e”]
输出: [“b”,“l”,“u”,“e”,” “,“i”,“s”,” “,“s”,“k”,“y”,” ",“t”,“h”,“e”]

class Solution {
public:
    void reverseWords(vector<char>& s) {
        int start = 0;
        for (int i = 0; i < s.size(); i++) {
            if (i + 1 >= s.size() || s[i + 1] == ' ') {
                reverse(s, start, i);
                start = i + 2;
            }
        }
        reverse(s, 0, s.size() - 1);
    }
    void reverse(vector<char>& t, int p, int q) {
        if (p < 0 || q >= t.size()) return;
        while (p < q) swap(t[p++], t[q--]);
    }
};

243. 最短单词距离

石器时代 —— Leetcode刷题日记(精选算法200题)_第2张图片

class Solution {
public:
    int shortestDistance(vector<string>& words, string word1, string word2) {
        int p1 = -1, p2 = -1;
        int res = words.size();
        for (int i = 0; i < words.size(); i++) {
            if (word1 == words[i]) p1 = i;
            if (word2 == words[i]) p2 = i;
            if (p1!=-1 && p2!=-1)res = min(res, abs(p1-p2));
        }
        return res;
    }
};

244. 最短单词距离 II

  • 请设计一个类,使该类的构造函数能够接收一个单词列表。然后再实现一个方法,该方法能够分别接收两个单词 word1 和 word2,并返回列表中这两个单词之间的最短距离。您的方法将被以不同的参数调用 多次。
class WordDistance {
private:
    unordered_map<string, vector<int>> m;
public:
    WordDistance(vector<string>& words) {
        m.clear();
        for (int i = 0; i < words.size(); i++) {
            m[words[i]].push_back(i);
        }
    }
    int shortest(string word1, string word2) {
        vector<int> w1 = m[word1], w2 = m[word2];
        int res = INT_MAX;
        // for (int i = 0; i < w1.size(); i++) {
        //     for (int j = 0; j < w2.size(); j++) {
        //         res = min(res, abs(w1[i] - w2[j]));
        //     }
        // }
        int i = 0, j = 0;
        while(i < w1.size() && j < w2.size()) {
            res = min(res, abs(w1[i] - w2[j]));
            if (w1[i] < w2[j]) i++;
            else j++; 
        }
        return res;
    }
};

245. 最短单词距离 III

  • 函数形式的244
class Solution {
public:
    int shortestWordDistance(vector<string>& words, string word1, string word2) {
        unordered_map<string, vector<int>> m;
        for (int i = 0; i < words.size(); i++) {
            m[words[i]].push_back(i);
        }
        vector<int> w1 = m[word1], w2 = m[word2];
        int res = INT_MAX;
        int start = 0;
        if (word1 == word2) start = -1;
        for (int i = 0; i < w1.size(); i++) {
            for (int j = (start == 0 ? 0 : i + 1); j < w2.size(); j++) {
                res = min(res, abs(w1[i] - w2[j]));
            }
        }
        return (res == INT_MAX && start == -1) ? 0:res;
    }
};
  • 双指针比较快
class Solution {
public:
    int shortestWordDistance(vector<string>& words, string word1, string word2) {
        int p1 = -1, p2 = -1;
        int res = words.size();
        for (int i = 0; i < words.size(); i++) {
            if (word1 == words[i]) {
                p1 = i;
                if (p1!=-1 && p2!=-1 && p1!=p2) 
                // 和243区别就是每个判断都要判断下
                    res = min(res, abs(p1-p2));
            }
            if (word2 == words[i]) {
                p2 = i;
                if (p1!=-1 && p2!=-1 && p1!=p2)
                    res = min(res, abs(p1-p2));
            }
        }
        return res;
    }
};

250. 统计同值子树

给定一个二叉树,统计该二叉树数值相同的子树个数。
同值子树是指该子树的所有节点都拥有相同的数值。
PS:C++中使用递归,不能把递归函数放在条件判断中,因为短路效应会导致可能某个分支中的递归没有进行!!!

  • W1 从上往下
class Solution {
public:
    int countUnivalSubtrees(TreeNode* root) {
        if (!root) return 0;
        int res = 0;
        dfs(root, res);
        return res;
    }
    bool dfs(TreeNode* node, int& res) {
        if (!node->left && !node->right) {
            res++;
            return true;
        }
        bool isUniv = true;
        if (node->left) {
            isUniv = dfs(node->left, res) && isUniv && 
            // isUniv要放在后面 否则会有短路效应
                node->val == node->left->val;
        } 
        if (node->right) {
            isUniv = dfs(node->right, res) && isUniv && 
                node->val == node->right->val;
        }
        res += isUniv;
        return isUniv;
    }
};
  • W2 从底往上
class Solution {
public:
    int countUnivalSubtrees(TreeNode* root) {
        int res = 0;
        dfs(root, res, 0);
        return res;
    }
    bool dfs(TreeNode* node, int& res, int val) {
        if (!node) return true;
        bool leftF = dfs(node->left,res,node->val);
        bool rightF = dfs(node->right,res,node->val);
        if (!leftF || !rightF) return false; // 又是短路效应
        res++;
        return node->val == val;
    }
};

255. 验证前序遍历序列二叉搜索树

  • DFS
class Solution {
public:
    bool verifyPreorder(vector<int>& preorder) {
        if (preorder.empty()) return true;
        return dfs(preorder, 0, preorder.size() - 1);
    }
    bool dfs(vector<int>& vec, int p, int q) {
        if (q >= vec.size() || p >= q) return true;
        int root = vec[p];
        int pos = p + 1;
        for (; pos <= q; pos++) {
            if (vec[pos] > root) break;
        }
        for (int i = pos; i <= q; i++) {
            if (vec[i] < root) return false;
        }
        if (!dfs(vec,p+1,pos-1)) return false;
        return dfs(vec,pos,q);
    }
};
  • 单减栈
class Solution {
public:
    bool verifyPreorder(vector<int>& preorder) {
        stack<int> stack;
        int min = INT_MIN;
        for (int i = 0; i < preorder.size(); ++i) {
            if (preorder[i] < min) return false;
            while (!stack.empty() && preorder[i] > preorder[stack.top()]) {
                min = preorder[stack.top()];
                stack.pop();
            }
            stack.push(i);
        }
        return true;
    }
};

你可能感兴趣的:(CS,-,Algo)