2021年10月LeetCode每日一题

目录

    • (模拟-简单)旅行终点站
    • (位运算-简单)数字转换为十六进制数
    • (模拟-中等)分数到小数
    • (模拟-简单)密钥格式化
    • (模拟-中等)窥探迭代器
    • (排序-简单)第三大的数
    • (模拟-简单)字符串中的单词数
    • (字符串哈希-中等)重复的DNA序列
    • (集合-困难)
    • (二分-简单)排列硬币
    • (递归-困难)整数转换英文表示
    • (除法-中等)两数相除
    • (模拟-简单)Fizz Buzz
    • (二分-简单)剑指 Offer II 069. 山峰数组的顶部
    • (模拟-中等)外观数列
    • (递归-困难)给表达式添加运算符
    • (递归-中等)二叉搜索树中第K小的元素
    • (字典树-中等)添加与搜索单词
    • (数学-简单)最小操作次数使数组元素相等
    • (数组-简单)加一
    • (杂题-中等)求众数II
    • (数学-简单)构造矩形

(模拟-简单)旅行终点站

题目链接

class Solution {
public:
    string destCity(vector<vector<string>>& p) {
        int n = p.size();
        unordered_map<string,int> mp;
        for (int i = 0; i < n; i ++){
             mp[p[i][0]]++;
             if(mp[p[i][1]] == 1)continue;
             mp[p[i][1]] = 0;
        }
        for (auto it = mp.begin(); it != mp.end(); it ++){
            if (it->second == 0){
                return it->first;
            }
        }
        return "";
    }
};

(位运算-简单)数字转换为十六进制数

题目链接

32位二进制可以表示8位16进制数
原码 + 取反 + 1 = 补码
补码 + 取反 + 1 = 原码

class Solution {
public:
    string toHex(int num) {
        if (num == 0) return "0";
        string sb;
        for (int i = 7; i >= 0; i --) {
            int val = (num >> (4 * i)) & 0xf;   //一次取4位进行比较
            if (sb.length() > 0 || val > 0) {	//去除前导零
                char digit = val < 10 ? (char) ('0' + val) : (char) ('a' + val - 10);
                sb.push_back(digit);
            }
        }
        return sb;
    }
};

(模拟-中等)分数到小数

题目链接
借鉴小爱

typedef long long ll;
class Solution {
public:
    string fractionToDecimal(int numerator, int denominator) {
        ll n = numerator, d = denominator;
        string res = "";
        // 计算整数部分
        // 判断负数
        if(n * d < 0) res += "-";

        ll a = n / d;
        if(a < 0) a *= -1;
        res += to_string(a);

        if(n < 0) n *= -1;
        if(d < 0) d *= -1;

        // 计算小数部分
        n %= d;
        if(n == 0) return res;  // 无小数

        res += ".";
        // 连除
        // 哈希表记录是否有数组第二次出现
        unordered_map<int, int> st;
        string t = "";
        int index = 0;
        while(n && !st.count(n)) {
            st[n] = index++;
            n *= 10;
            t += to_string(n/d);
            n %= d;
        }

        if(n != 0) {
            // 说明出现了循环,此时对循环部分 [st[n], index] 加括号
            res += t.substr(0, st[n]) + "(" + t.substr(st[n]) + ")";
        } else res += t;


        return res;
    }
};

(模拟-简单)密钥格式化

题目链接

class Solution {
public:
    string licenseKeyFormatting(string s, int k) {
        int n = s.size(),num = 0;
        string st;
        for (int i = 0; i < n; i ++){
            if (s[i] != '-'){
                num ++;
                if ('a' <= s[i] && s[i] <= 'z')st.push_back(s[i] - 32);
                else st.push_back(s[i]);
            }
        }
        string res = "";
        n = st.size();
        for (int i = n - 1,j = 1; i >= 0; i --,j ++){
            res += st[i];
            if (j % k == 0 && j != n)res += '-';
        }
        reverse(res.begin(),res.end());
        return res;
    }
};

(模拟-中等)窥探迭代器

题目链接
官 方 题 解 官方题解
2021年10月LeetCode每日一题_第1张图片

class PeekingIterator : public Iterator {
public:
    PeekingIterator(const vector<int>& nums) : Iterator(nums) {
        flag = Iterator::hasNext();
        if (flag) {
            nextElement = Iterator::next();
        }
    }
    int peek() {
        return nextElement;
    }
    int next() {
        int ret = nextElement;
        flag = Iterator::hasNext();
        if (flag) {
            nextElement = Iterator::next();
        }
        return ret;
    }
    bool hasNext() const {
        return flag;
    }
private:
    int nextElement;
    bool flag;
};

(排序-简单)第三大的数

题目链接

class Solution {
public:
    int thirdMax(vector<int>& n) {
        sort(n.begin(),n.end());
        n.erase(unique(n.begin(),n.end()),n.end());
        int le = n.size();
        if (le < 3)return n[le-1];
        return n[le-3];
    }
};

(模拟-简单)字符串中的单词数

题目链接
一 定 要 读 好 题 目 每 个 字 一定要读好题目每个字

class Solution {
public:
    int countSegments(string s) {
        int res = 0;
        for (int i = 0; i < s.size(); i++)
            if ((i == 0 || s[i - 1] == ' ') && s[i] != ' ')
                res++;
        return res;
    }
};

(字符串哈希-中等)重复的DNA序列

题目链接

class Solution {
public:
    vector<string> findRepeatedDnaSequences(string s) {
        vector<string> res;
        int n = s.size();
        if (n <= 10)return res;
        map<string,int> mp;
        string st = "";
        int i = 0;
        for (; i < 10; i ++)st+=s[i];
        mp[st] ++;
        for (; i < n; i ++){
            st = st.substr(1,10) + s[i];
            mp[st] ++;
            if (mp[st] == 2)res.push_back(st);
        }
        return res;
    }
};

(集合-困难)

题目链接 官方题解
看 官 方 题 解 + 下 面 代 码 注 释 看官方题解+下面代码注释 +

class SummaryRanges {
private:
    map<int, int> mp;
public:
    SummaryRanges() {}
    void addNum(int val) {
        auto l1 = mp.upper_bound(val);//查找第一个大于val的位置,不存在时返回mp.end();说明这个val比之前所有的数都大
        
        auto l0 = (l1 == mp.begin() ? mp.end() : prev(l1));//如果l1等于mp.begin()那么说明这个数比所有的数都小,然后将l0 = mp.end(),否者l0 = pre(l1);

        if (l0 != mp.end() && l0->first <= val && val <= l0->second){
            // 情况一
            return;
        }else {
            //判断是否靠近左边界
            bool left_aside = (l0 != mp.end() && l0->second + 1 == val);
            //判断是否靠近有边界
            bool right_aside = (l1 != mp.end() && l1->first - 1 == val);
            if (left_aside && right_aside) {
                // 情况四
                int left = l0->first, right = l1->second;
                mp.erase(l0);
                mp.erase(l1);
                mp.emplace(left, right);
            } else if (left_aside) {
                // 情况二
                ++l0->second;
            } else if (right_aside) {
                // 情况三
                int right = l1->second;
                mp.erase(l1);
                mp.emplace(val, right);
            } else {
                // 情况五
                mp.emplace(val, val);
            }
        }
    }
    
    vector<vector<int>> getIntervals() {
        vector<vector<int>> ans;
        for (const auto& [left, right]: mp) {
            ans.push_back({left, right});
        }
        return ans;
    }
};

(二分-简单)排列硬币

题目链接

class Solution {
public:
    int arrangeCoins(int n) {
        int l = 1,r = 2 << 16 + 10;
        while(l < r){
            long long mid = l + r + 1 >> 1;
            if (mid * (mid + 1) / 2 <= n)l = mid;
            else r = mid - 1;
        }
        return l;
    }
};

(递归-困难)整数转换英文表示

题目链接

题意:一个整数翻译成英文数字

挺 有 意 思 的 挺有意思的

class Solution {
public:
    vector<string> singles = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"};
    vector<string> teens = {"Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
    vector<string> tens = {"", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
    vector<string> thousands = {"", "Thousand", "Million", "Billion"};

    string numberToWords(int num) {
        if (num == 0) return "Zero";
        string sb;
        for (int i = 3, unit = 1000000000; i >= 0; i--, unit /= 1000) {
            int curNum = num / unit;
            if (curNum != 0) {
                num -= curNum * unit;
                string curr;
                recursion(curr, curNum);
                curr = curr + thousands[i] + " ";
                sb = sb + curr;
            }
        }
        while (sb.back() == ' ') {
            sb.pop_back();
        }
        return sb;
    }

    void recursion(string & curr, int num) {
        if (num == 0) {
            return;
        } else if (num < 10) {
            curr = curr + singles[num] + " ";
        } else if (num < 20) {
            curr = curr + teens[num - 10] + " ";
        } else if (num < 100) {
            curr = curr + tens[num / 10] + " ";
            recursion(curr, num % 10);
        } else {
            curr = curr + singles[num / 100] + " Hundred ";
            recursion(curr, num % 100);
        }
    }
};

(除法-中等)两数相除

题目链接

class Solution {
public:
    int divide(int dividend, int divisor) {
        // 考虑被除数为最小值的情况
        if (dividend == INT_MIN) {
            if (divisor == 1) return INT_MIN;
            if (divisor == -1)  return INT_MAX;
        }
        // 考虑除数为最小值的情况
        if (divisor == INT_MIN) return dividend == INT_MIN ? 1 : 0;

        // 考虑被除数为 0 的情况
        if (dividend == 0) return 0;
        
        // 一般情况,使用二分查找
        // 将所有的正数取相反数,这样就只需要考虑一种情况
        bool rev = false;
        if (dividend > 0) {
            dividend = -dividend;
            rev = !rev;
        }
        if (divisor > 0) {
            divisor = -divisor;
            rev = !rev;
        }

        // 快速乘
        auto quickAdd = [](int y, int z, int x) {
            // x 和 y 是负数,z 是正数
            // 需要判断 z * y >= x 是否成立
            int result = 0, add = y;
            while (z) {
                if (z & 1) {
                    // 需要保证 result + add >= x
                    if (result < x - add) {
                        return false;
                    }
                    result += add;
                }
                if (z != 1) {
                    // 需要保证 add + add >= x
                    if (add < x - add) {
                        return false;
                    }
                    add += add;
                }
                // 不能使用除法
                z >>= 1;
            }
            return true;
        };
        
        int left = 1, right = INT_MAX, ans = 0;
        while (left <= right) {
            // 注意溢出,并且不能使用除法
            int mid = left + ((right - left) >> 1);
            bool check = quickAdd(divisor, mid, dividend);
            if (check) {
                ans = mid;
                // 注意溢出
                if (mid == INT_MAX) break;
                left = mid + 1;
            }else right = mid - 1;
        }
        return rev ? -ans : ans;
    }
};

(模拟-简单)Fizz Buzz

题目链接

class Solution {
public:
    vector<string> fizzBuzz(int n) {
        vector<string> res;
        for (int i = 1; i <= n; i ++){
            if (i % 3 == 0 && i % 5 == 0)res.push_back("FizzBuzz");
            else if (i % 3 == 0) res.push_back("Fizz");
            else if (i % 5 == 0) res.push_back("Buzz");
            else res.push_back(""+to_string(i));
        }
        return res;
    }
};

(二分-简单)剑指 Offer II 069. 山峰数组的顶部

题目链接
2021年10月LeetCode每日一题_第2张图片

class Solution {
public:
    int peakIndexInMountainArray(vector<int>& arr) {
        int n = arr.size();
        int l = 1,r = n;
        while(l < r){
            int mid = l + r >> 1;
            if (arr[mid] > arr[mid + 1])r = mid;
            else l = mid + 1;
        }
        return l;
    }
};

(模拟-中等)外观数列

题目链接

class Solution {
public:
    string countAndSay(int n) {
        string res = "1";
        for (int i = 2; i <= n; i ++) {
            string st = "";
            int l = 0,r = 0,le = res.size();
            while (r < le) {
                while (r < le && res[r] == res[l]) r ++;
                st += to_string(r - l) + res[l];
                l = r;
            }
            res = st;
        }
        
        return res;
    }
};

(递归-困难)给表达式添加运算符

非 常 值 得 回 味 的 一 道 题 非常值得回味的一道题
2021年10月LeetCode每日一题_第3张图片
题目链接

typedef long long ll;
class Solution {
public:
    string num;
    vector<string> res;
    int n, target;

    void dfs(string s, int index, ll ans, ll mul) {
        if (index == n) {
            if (ans == target) res.push_back(s);
            return;
        }

        // 当前表达式长度
        int m = s.size();
        if (index > 0) s.push_back(0); // 占位(扩充一个位子),方便下面填充符号
        ll val = 0;
        // 枚举截取的数字长度(取多少位),注意数字可以是单个0但不能有前导零
        for (int j = index; j < n && (j == index || num[index] != '0'); j ++) {
            val = val * 10 + num[j] - '0';
            s.push_back(num[j]);
            if (index == 0) { // 表达式开头不能添加符号
                dfs(s, j + 1, val, val);
            } else {
                s[m] = '+';
                dfs(s, j + 1, ans + val, val);
                s[m] = '-';
                dfs(s, j + 1, ans - val, -val);
                s[m] = '*';
                dfs(s, j + 1, ans - mul + mul * val, mul * val);
            }
        }
    };

    vector<string> addOperators(string _num, int _target) {
        num = _num;
        n = _num.length();
        target = _target;
        string s;
        dfs(s, 0, 0, 0);
        return res;
    }
};

(递归-中等)二叉搜索树中第K小的元素

题目链接
2021年10月LeetCode每日一题_第4张图片

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int res;
    int dfs(TreeNode* root,int k){
        if (root == nullptr)return 0;
        int l = dfs(root->left,k);
        if (l + 1 == k) res = root->val;
        int r = dfs(root->right,k-l-1);
        return l + r + 1;
        
    }
    int kthSmallest(TreeNode* root, int k) {
        dfs(root,k);
        return res;
    }
};

(字典树-中等)添加与搜索单词

题目链接

struct TrieNode{
    vector<TrieNode *> child;
    bool isEnd;
    TrieNode() {
        this->child = vector<TrieNode *>(26,nullptr);
        this->isEnd = false;
    }
};
void insert(TrieNode * root, const string & word) {
    TrieNode * node = root;
    for (auto c : word) {
        if (node->child[c - 'a'] == nullptr) {
            node->child[c - 'a'] = new TrieNode();
        }
        node = node->child[c - 'a'];
    }
    node->isEnd = true;
}

class WordDictionary {
public:
    WordDictionary() {
        trie = new TrieNode();
    }
    
    void addWord(string word) {
        insert(trie,word);
    }
    
    bool search(string word) {
        return dfs(word, 0, trie);
    }

    bool dfs(const string & word,int index,TrieNode * node) {
    if (index == word.size()) {
            return node->isEnd;    
        }
        char ch = word[index];
        if (ch >= 'a' && ch <= 'z') {
            TrieNode * child = node->child[ch - 'a'];
            if (child != nullptr && dfs(word, index + 1, child)) {
                return true;
            }
        } else if (ch == '.') {
            for (int i = 0; i < 26; i++) {
                TrieNode * child = node->child[i];
                if (child != nullptr && dfs(word, index + 1, child)) {
                    return true;
                }
            }
        }
        return false;
    }
private:
    TrieNode * trie;
};

(数学-简单)最小操作次数使数组元素相等

转换思维
把n-1个增大,就是把那一个减小
题目链接

class Solution {
public:
    int minMoves(vector<int>& nums) {
        int res = 0,mi = 9999999999,n = nums.size();
        for (int i = 0; i < n; i ++)mi = min(mi,nums[i]);
        for (int i = 0; i < n; i ++)res += nums[i] - mi;
        return res;
    }
};

(数组-简单)加一

题目链接

class Solution {
public:
    vector<int> plusOne(vector<int>& d) {
        int tmp = 1,n = d.size();
        for (int i = n - 1; i >= 0; i --){
            if (d[i] + tmp >= 10){
                d[i] = (d[i] + tmp)%10;
                tmp = 1;
            }else {
                d[i] = d[i] + tmp;
                tmp = 0;
                break;
            }
        }
        if (tmp)d.insert(d.begin(),1);
        return d;
    }
};

(杂题-中等)求众数II

题意:给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。

进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1)的算法解决此问题。

普通写法
就直接哈希

class Solution {
public:
    vector<int> majorityElement(vector<int>& nums) {
        int n = nums.size();
        vector<int> ans;
        unordered_map<int, int> cnt;
        for (auto & v : nums) cnt[v]++;
        for (auto & v : cnt) 
            if (v.second > n / 3) 
                ans.push_back(v.first);
        return ans;
    }
};

进阶写法
因为数量大于等于n/3的数最多有两个。

class Solution {
public:
    vector<int> majorityElement(vector<int>& nums) {
        vector<int> ans;
        int element1 = 0,element2 = 0,vote1 = 0,vote2 = 0;

        for (auto & num : nums) {
            if (vote1 > 0 && num == element1) { //如果该元素为第一个元素,则计数加1
                vote1++;
            } else if (vote2 > 0 && num == element2) { //如果该元素为第二个元素,则计数加1
                vote2++;
            } else if (vote1 == 0) { // 选择第一个元素
                element1 = num;
                vote1++;
            } else if (vote2 == 0) { // 选择第二个元素
                element2 = num;
                vote2++;
            } else { //如果三个元素均不相同,则相互抵消1次
                vote1--;
                vote2--;
            }
        }
        //到这里只能说明这两个数最有可能是大于等于n/3的两个元素,还需要在遍历一次确认
        int cnt1 = 0,cnt2 = 0;
        for (auto & num : nums) {
            if (vote1 > 0 && num == element1) cnt1++;
            if (vote2 > 0 && num == element2) cnt2++;
        }
        // 检测元素出现的次数是否满足要求
        if (vote1 > 0 && cnt1 > nums.size() / 3) ans.push_back(element1);
        if (vote2 > 0 && cnt2 > nums.size() / 3) ans.push_back(element2);
        
        return ans;
    }
};

(数学-简单)构造矩形

题目链接

class Solution {
public:
    vector<int> constructRectangle(int a) {
        int t = sqrt(a);
        vector<int> res;
        for (int i = t; i >= 1; i --){
            if (a % i == 0){
                res.push_back(i);
                res.push_back(a / i);
                break;
            }
        }
        sort(res.begin(),res.end());
        reverse(res.begin(),res.end());
        return res;
    }
};

你可能感兴趣的:(LeetCode每日一题,leetcode,算法,c++)