LeetCode高频面试题记录(四)

戳气球 困难
原理参考这篇文章:https://leetcode-cn.com/problems/burst-balloons/solution/c-dong-tai-gui-hua-qu-jian-dp-mo-ban-ti-by-wilson7/

class Solution {
public:
    int maxCoins(vector<int>& nums) {
        nums.insert(nums.begin(),1); nums.push_back(1);
        //dp[i][j]表示第i至第j个元素这个区间能获得的最大硬币数
        vector<vector<int>> dp(nums.size(), vector<int>(nums.size(), 0));   
        for(int r=2; r<nums.size(); r++)        //r为区间长度
            for(int i=0; i<nums.size()-r; i++){ //i为左区间
                int j = i + r;                  //j为右区间
                for(int k=i+1; k<j; k++)
                    dp[i][j]=max(dp[i][j],dp[i][k]+dp[k][j]+nums[i]*nums[k]*nums[j]);
            }
        return dp[0][nums.size()-1];
    }
};

编辑距离 困难
想得出就想得出,想不出就想不出,尽力理解吧

class Solution {
public:
    int minDistance(string word1, string word2) {
        int m = word1.size(), n = word2.size();
        int dp[m + 1][n + 1];
        for (int i = 0; i <= m; i++) 
            dp[i][0] = i;
        for (int j = 1; j <= n; j++) 
            dp[0][j] = j;
        for (int i = 1; i <= m; i++) 
            for (int j = 1; j <= n; j++) {
                if (word1[i - 1] == word2[j - 1]) //不用改的情况
                    dp[i][j] = dp[i - 1][j - 1];
                else //增、删、改三者取最小
                    dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
            }
        return dp[m][n];
    }
};

最长连续序列 困难
并查集
初始化的时候先把数组里每个元素初始化为他的下一个数;
并的时候找他能到达的最远的数字就可以了。

class Solution {
public:
    unordered_map<int,int> a;
    int find(int x){
        return a.count(x) ? a[x]=find(a[x]) : x;
    }
    int longestConsecutive(vector<int>& nums) {
        for(auto i:nums)
            a[i] = i+1;
        int ans = 0;
        for(auto i:nums){
            int y = find(i+1);
            ans = max(ans, y-i);
        }
        return ans;
    }
};

哈希表法

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        unordered_map<int,int> a;
        for(auto i:nums)
            a[i] = i;
        int ans = 0;
        for(int i=nums.size()-1; i>=0; --i){
            if(!a.count(nums[i]-1)){
                int cur = nums[i];
                while(a.count(cur+1)){
                    ++cur;
                }
                ans=max(ans,cur-nums[i]+1);
            }
        }
        return ans;
    }
};

二叉树的序列化与反序列化 困难

class Codec {//根据题意,我们可以任意选择序列化的方式,前序最容易构建树,我们选择前序
public:
    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        string res;
        dfs_s(root, res);
        return res;
    }
    // 前序遍历序列转化为字符串
    void dfs_s(TreeNode* root, string& res) {
        if (!root) {
            res += "null ";
            return;
        }
        res += to_string(root->val) + ' ';
        dfs_s(root->left, res);
        dfs_s(root->right, res);
    }
    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        // 开始遍历索引
        int u = 0;
        return dfs_d(data, u);
    }
    TreeNode* dfs_d(string& data, int& u) {
        if (u >= data.size()) return NULL;
        if (data[u] == 'n') {//处理null
            u = u + 5;
            return NULL;
        }
        int val = 0, sign = 1;
        if (data[u] == '-') sign = -1, u ++ ;
        while(data[u] != ' '){val = val * 10 + data[u] - '0'; u++;}
        val *= sign;
        u = u + 1 ;
        auto root = new TreeNode(val);
        root->left = dfs_d(data, u);
        root->right = dfs_d(data, u);
        return root;
    }
};

滑动窗口最大值 困难
这道题用deque,保持队列头部始终是最大值

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int> res;
        deque<int> que;
        int left=0, right=0;
        for (auto num:nums){
            while(!que.empty() && que.back() < num){
                que.pop_back();
            }
            que.push_back(num);
            right++;
            if (right-left >=k){
                res.push_back(que.front());
                if (nums[left] == que.front())
                    que.pop_front();
                left++;
            }
        }
        return res;
    }
};

缺失的第一个正数 困难

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        if (nums.empty()) return 1;
        vector<int> vec(nums.size(), 0);
        for (auto num:nums){
            if (num > 0 && num <= nums.size())
                vec[num-1] = 1;
        }
        int res = -1;
        for (int i=0; i<vec.size(); i++){
            if (vec[i] == 0){
                res = i+1;
                break;
            }
        }
        if (res == -1) return nums.size()+1;
        return res;
    }
};

剑指 Offer 51. 数组中的逆序对 困难

class Solution {
    int res = 0;
    void mergeSort(vector<int>& nums, vector<int>& temp, int l, int r){
        if (l >= r) return;
        int mid = (l + r) / 2;
        mergeSort(nums, temp, l, mid);
        mergeSort(nums, temp, mid+1, r);
        int i=l, j=mid+1; int t=0;
        while (i<=mid && j<=r){
            if (nums[i] <= nums[j]){
                res += (j - (mid + 1));//这里增加一行
                temp[t++] = nums[i++];
            }
            else 
                temp[t++] = nums[j++];
        }
        while (i <= mid) {temp[t++] = nums[i++]; res += (j-(mid+1));}//这里增加一行
        while (j <= r) temp[t++] = nums[j++];
        t = 0;
        for (int i=l; i<=r; i++)
            nums[i] = temp[t++];
    }
public:
    int reversePairs(vector<int>& nums) {
        vector<int> temp(nums.begin(), nums.end());
        mergeSort(nums, temp, 0, nums.size()-1);
        return res;
    }
};

逆波兰表达式求值(栈实现) 中等

class Solution {
public:
    int ans;
    int evalRPN(vector<string>& tokens) {
        stack<int> stk;
        int str_mid1, str_mid2;
        for (auto v_mate : tokens) {
            if (v_mate == "+") {
                str_mid1 = stk.top();
                stk.pop();
                str_mid2 = stk.top();
                stk.pop();
                stk.push(str_mid2 + str_mid1);
            }
            else if (v_mate == "-") {
                str_mid1 = stk.top();
                stk.pop();
                str_mid2 = stk.top();
                stk.pop();
                stk.push(str_mid2 - str_mid1);
            }
            else if (v_mate == "*") {
                str_mid1 = stk.top();
                stk.pop();
                str_mid2 = stk.top();
                stk.pop();
                stk.push(str_mid2 * str_mid1);
            }
            else if (v_mate == "/") {
                str_mid1 = stk.top();
                stk.pop();
                str_mid2 = stk.top();
                stk.pop();
                stk.push(str_mid2 / str_mid1);
            }
            else stk.push(atoi(v_mate.c_str()));
        }
        ans = stk.top();
        return ans;
    }
};

字典序的第K小数字 困难

class Solution {
public:
    int findKthNumber(int n, int k) {
        int cur = 1;
        --k;
        while (k > 0){
            //first是当前前缀, last是下一个前缀
            long long first=cur, last=cur+1, step=0;
            while(first <= n){
                //下一个前缀的起点减去当前前缀的起点
                step += min((long long)n+1,last) - first;
                first *= 10;
                last *= 10;
            }
            if(step <= k){
                k -= step;
                cur++;
            }
            else{
                k--;
                cur *= 10;
            }
        }
        return cur;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

华为云计算搬砖工

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值