【LeetCode第 296 场周赛】?!?我AK了?!?

话不多说,先上图!!!

在这里插入图片描述

纪念第一次力扣AK!!!


快乐 总是 这么 短暂

让我们一起来体验这场美妙的算法之旅吧~~

文章目录

  • 极大极小游戏
  • 划分数组使最大差为 k
  • 替换数组中的元素
  • 设计一个文本编辑器
    • 写在最后

神奇AK传送门


极大极小游戏

题目

【LeetCode第 296 场周赛】?!?我AK了?!?_第1张图片


思路

按照题目模拟

  • 奇数取 m i n {min} min
  • 偶数取 m a x {max} max
  • 每轮结束后,原数组要改变为新数组
  • l e n = = 1 {len == 1} len==1 退出循环

代码

class Solution {
public:
    int minMaxGame(vector<int>& nums) {
        if(nums.size() == 1) return nums[0];
        for (int i = 0; i < nums.size(); i++, i = 0) {
            int n = nums.size() / 2;
            vector<int> a(n, 0);
            for (int j = 0; j < n; j++) {
                if(j % 2 == 0) a[j] = min(nums[j * 2], nums[j * 2 + 1]);
                else a[j] = max(nums[j * 2], nums[j * 2 + 1]);
            }
            nums = a;
            if(n == 1) return nums[0];
        }
        return -1;
    }
};

划分数组使最大差为 k

题目

【LeetCode第 296 场周赛】?!?我AK了?!?_第2张图片


思路

题意:划分最少子序列,满足子序列中极大极小值只差不超过 k {k} k

很显然,一眼贪心。因为能凑成一组的尽可能地都塞进一组中,这样是更优的。

从最大值来看,对于全局最大值 m a x {max} max,我一定会让所有在 [ m a x − k , m a x ] {[max - k, max]} [maxk,max] 之间的值分为一组。同理对于 m a x − k − 1 {max -k - 1} maxk1 也是如此。


代码

class Solution {
public:
    int partitionArray(vector<int>& a, int k) {
        sort(a.begin(), a.end());
        int n = a.size();
        int res = 1;
        int last = a[0], now = 0;
        for (int i = 1; i < n; i++) {
            now = a[i];
            if(now - last <= k) continue;
            else {
                last = a[i];
                res ++;
            }
        }
        return res;
    }
};

替换数组中的元素

题目

【LeetCode第 296 场周赛】?!?我AK了?!?_第3张图片


思路

这题好写在于,题目给定了每一次操作 o p e r a t i o n s {operations} operations 中,要改变的值 p r e {pre} pre 一定存在于数组总,而改后的值 s u f {suf} suf 一定不存在于数组中。

由此我们直接唯一索引,开个全局 m a p {map} map,改要改的地方即可。


代码

class Solution {
public:
    map<int, int> mp;
    vector<int> arrayChange(vector<int>& a, vector<vector<int>>& op) {
        for (int i = 0; i < a.size(); i++) {
            mp[a[i]] = i;
        }
        for (int i = 0; i < op.size(); i++) {
            int pre = op[i][0], suf = op[i][1];
            int now = mp[pre];
            a[mp[pre]] = suf;
            mp[suf] = now;
        }
        return a;
    }
};

设计一个文本编辑器

题目

【LeetCode第 296 场周赛】?!?我AK了?!?_第4张图片


思路

一开始我思路从维护一个 d e q u e {deque} deque 变为两个 d e q u e {deque} deque

后来发现,这不就是我之前做过的类似的一道题目嘛???而且数据范围是 ∑ 1 0 4 {\sum10^4} 104 次操作,每次最多还只是移动 40 40 40 次光标,以及取 10 10 10 个左侧字符。(这不纯暴力就能过的嘛)

两个栈 L   、 R L\ 、R L R )来模拟光标 之前之后 的文本字符!!!

规定 光标 即为 L 、 R 之 间 L、R之间 LR

【LeetCode第 296 场周赛】?!?我AK了?!?_第5张图片

  • a d d T e x t ( s t r i n g   t e x t ) addText(string\ text) addText(string text):【将 t e x t text text 添加到光标所在位置】

    • 只向 L {L} L 加字符
  • d e l e t e T e x t ( i n t   k ) deleteText(int\ k) deleteText(int k) :【删除光标左边 k k k 个字符】

    • 只对 L {L} L 删字符
  • c u r s o r L e f t ( i n t   k ) cursorLeft(int\ k) cursorLeft(int k):【将光标向左移动 k k k 次】

    • 显然 L L L 顶部需要弹出 k k k 个到 R R R 中,并保证 L L L 非空
    • 对于光标左侧min(10, len)个字符,我们直接暴力开一个栈 t m p tmp tmp L L L弹出来到 t m p tmp tmp中,字符加给 r e s res res,然后 t m p tmp tmp 在弹回给 L L L
    • 注意 r e s res res 是逆序的
  • c u r s o r R i g h t ( i n t   k ) cursorRight(int\ k) cursorRight(int k):【将光标向右移动 k k k 次】

    • 显然 R R R 顶部需要弹出 k k k 个到 R R R 中,并保证 R R R 非空
    • 同理

代码

class TextEditor {
public:
    stack<char> L, R;
    
    TextEditor() {
        L = stack<char>();
        R = stack<char>();
    }
    // 只向 L 加字符
    void addText(string text) {
        for (auto &x: text) {
            L.push(x);
        }
    }
    // 只对 L 删字符
    int deleteText(int k) {
        int res = 0;
        while(L.size() && k) {
            L.pop();
            res ++;
            k -= 1;
        }
        return res;
    }
    
    string cursorLeft(int k) {
    	// 先将L中弹出道R中
        while(L.size() && k) {
            char c = L.top();
            L.pop();
            R.push(c);
            k -= 1;
        }
        stack<char> tmp;
        int val = 10;
        string res = "";
        // 在去弹出光标左侧的min(10, len)个字符
        while(L.size() && val) {
            char c = L.top();
            L.pop();
            tmp.push(c);
            val -= 1;
            res += c;
        }
        reverse(res.begin(), res.end()); // 记得要逆序回来
        // 返还给L
        while(tmp.size()) {
            L.push(tmp.top());
            tmp.pop();
        }
        return res;
    }
    
    string cursorRight(int k) {
        while(R.size() && k) {
            char c = R.top(); R.pop();
            L.push(c);
            k -= 1;
        }
        string res = "";
        stack<char> tmp;
        int val = 10;
        while(L.size() && val) {
            char c = L.top();
            L.pop();
            tmp.push(c);
            val -= 1;
            res += c;
        }
        while(tmp.size()) {
            L.push(tmp.top());
            tmp.pop();
        }
        reverse(res.begin(), res.end());
        return res;
    }
};

写在最后

感谢官方大大 给我一次 AK 的机会,虽然看到 评论区 都在 吐槽 这场 简单 ,但谁又能抵挡的住 AK 快乐


2022年6月5日12点11分

你可能感兴趣的:(力扣周赛,leetcode,贪心算法,算法,数据结构,c++)