[Leetcode Weekly Contest]296

链接:LeetCode

[Leetcode]2293. 极大极小游戏

给你一个下标从 0 开始的整数数组 nums ,其长度是 2 的幂。
对 nums 执行下述算法:

  1. 设 n 等于 nums 的长度,如果 n == 1 ,终止 算法过程。否则,创建 一个新的整数数组 newNums ,新数组长度为 n / 2 ,下标从 0 开始。
  2. 对于满足 0 <= i < n / 2 的每个 偶数 下标 i ,将 newNums[i] 赋值 为 min(nums[2 * i], nums[2 * i + 1]) 。
  3. 对于满足 0 <= i < n / 2 的每个 奇数 下标 i ,将 newNums[i] 赋值 为 max(nums[2 * i], nums[2 * i + 1]) 。
  4. 用 newNums 替换 nums 。
  5. 从步骤 1 开始 重复 整个过程。

执行算法后,返回 nums 中剩下的那个数字。

模拟遍历即可。

class Solution {
    public int minMaxGame(int[] nums) {
        while(nums.length!=1) {
            int[] nextNums = new int[nums.length/2];
            boolean minFlag = true;
            for(int i=0;i<nextNums.length;++i) {
                if(minFlag) nextNums[i] = Math.min(nums[2*i], nums[2*i+1]);
                else nextNums[i] = Math.max(nums[2*i], nums[2*i+1]);
                minFlag = !minFlag;
            }
            nums = nextNums;
        }
        return nums[0];
    }
}

[Leetcode]2294. 划分数组使最大差为 K

给你一个整数数组 nums 和一个整数 k 。你可以将 nums 划分成一个或多个 子序列 ,使 nums 中的每个元素都 恰好 出现在一个子序列中。
在满足每个子序列中最大值和最小值之间的差值最多为 k 的前提下,返回需要划分的 最少 子序列数目。
子序列 本质是一个序列,可以通过删除另一个序列中的某些元素(或者不删除)但不改变剩下元素的顺序得到。

由于选的是子序列,且只需要考虑每个子序列中的最小值和最大值,与子序列中元素的顺序无关,因此我们可以对数组排序。
排序后对数组分组,每组内的元素最大减最小不能超过 k。这可以通过遍历一遍数组来判断,并得到组数。

class Solution {
    public int partitionArray(int[] nums, int k) {
        Arrays.sort(nums);
        int res = 1;
        int pre = nums[0];
        for(int i=1;i<nums.length;++i) {
            if(nums[i] - pre > k) {
                res ++ ;
                pre = nums[i];
            }

        }
        return res;
    }
}

[Leetcode]2295. 替换数组中的元素

给你一个下标从 0 开始的数组 nums ,它包含 n 个 互不相同 的正整数。请你对这个数组执行 m 个操作,在第 i 个操作中,你需要将数字 operations[i][0] 替换成 operations[i][1] 。
题目保证在第 i 个操作中:

  • operations[i][0] 在 nums 中存在。
  • operations[i][1] 在 nums 中不存在。

请你返回执行完所有操作后的数组。
两种做法:正序(利用特殊条件) or 逆序(更加通用)。注意到 \(\textit{nums}\) 的元素互不相同,且每次操作总是将一个在 \(\textit{nums}\) 中的元素变成一个不在 \(\textit{nums}\) 中的元素,因此每次操作之后 \(\textit{nums}\) 的元素仍然互不相同。
用哈希表存储每个元素的位置,然后遍历 \(\textit{operations}\) 数组模拟即可。

如果 \(\textit{nums}\) 中有重复元素呢?有没有更加通用的做法?
\(x=\textit{operations}[i][0]\)\(y=\textit{operations}[i][1]\),我们可以倒着遍历 \(\textit{operations}\),同时用一个哈希表 \(\textit{mp}\) 将 x 映射到 \(\textit{mp}[y]\) 上,如果 \(\textit{mp}[y]\) 不存在则直接映射到 y 上。
例如,先把 1 变成 2,再把 2 变成 3,如果倒着来的话,就是 2 变成 3,那么对于 1 来说,可以直接知道最终是会变成 3 的。

class Solution {
    public int[] arrayChange(int[] nums, int[][] operations) {
        HashMap<Integer, Integer> hash = new HashMap<>();
        int n = operations.length;
        for(int i=n-1;i>=0;--i) {
            int pre = operations[i][0], nxt = operations[i][1];
            hash.put(pre, hash.getOrDefault(nxt, nxt));
        }
        for(int i=0;i<nums.length;++i) {
            nums[i] = hash.getOrDefault(nums[i], nums[i]);
        }
        return nums;
    }

    public int[] arrayChange2(int[] nums, int[][] operations) {
        HashMap<Integer, Integer> hash = new HashMap<>();
        for(int i=0;i<nums.length;++i) hash.put(nums[i], i);
        for(var operation: operations) {
            int pre = operation[0], nxt = operation[1];
            int idx = hash.get(pre);
            nums[idx] = nxt;
            hash.put(nxt, idx);
            hash.remove(pre);
        }
        return nums;
    }
}

[Leetcode]2296. 设计一个文本编辑器

请你设计一个带光标的文本编辑器,它可以实现以下功能:

  • 添加:在光标所在处添加文本。
  • 删除:在光标所在处删除文本(模拟键盘的删除键)。
  • 移动:将光标往左或者往右移动。
  • 当删除文本时,只有光标左边的字符会被删除。光标会留在文本内,也就是说任意时候 0 <= cursor.position <= currentText.length 都成立。

请你实现 TextEditor 类:

  • TextEditor() 用空文本初始化对象。
  • void addText(string text) 将 text 添加到光标所在位置。添加完后光标在 text 的右边。
  • int deleteText(int k) 删除光标左边 k 个字符。返回实际删除的字符数目。
  • string cursorLeft(int k) 将光标向左移动 k 次。返回移动后光标左边 min(10, len) 个字符,其中 len 是光标左边的字符数目。
  • string cursorRight(int k) 将光标向右移动 k 次。返回移动后光标左边 min(10, len) 个字符,其中 len 是光标左边的字符数目。

对顶栈。用两个栈头对头,光标的左右移动就相当于两个栈来回倒;对于插入和删除操作,就相当于在左边那个栈上入栈出栈。

class TextEditor {
    ArrayDeque<Character> queueleft = new ArrayDeque<>();
    ArrayDeque<Character> queueright = new ArrayDeque<>();
    int pos = 0;

    public TextEditor() {

    }

    public void addText(String text) {
        for(var ch:text.toCharArray()) {
            queueleft.push(ch);
        }
    }

    public int deleteText(int k) {
        int res = 0;
        for(int i=0;i<k;++i) {
            if(!queueleft.isEmpty()) queueleft.pop();
            else break;
            res ++;
        }
        return res;
    }

    public String cursorLeft(int k) {
        for(int i=0;i<k;++i) {
            if(queueleft.isEmpty()) break;
            char ch = queueleft.pop();
            queueright.push(ch);
        }
        String res = "";
        for(int i=0;i<10;++i) {
            if(queueleft.isEmpty()) break;
            res = queueleft.pop() + res;
        }
        addText(res);
        return res;
    }

    public String cursorRight(int k) {
        for(int i=0;i<k;++i) {
            if(queueright.isEmpty()) break;
            char ch = queueright.pop();
            queueleft.push(ch);
        }
        String res = "";
        for(int i=0;i<10;++i) {
            if(queueleft.isEmpty()) break;
            res = queueleft.pop() + res;
        }
        addText(res);
        return res;
    }
}

/**
 * Your TextEditor object will be instantiated and called as such:
 * TextEditor obj = new TextEditor();
 * obj.addText(text);
 * int param_2 = obj.deleteText(k);
 * String param_3 = obj.cursorLeft(k);
 * String param_4 = obj.cursorRight(k);
 */

参考:LeetCode

posted @ 2022-07-06 20:11  Jamest  阅读(40)  评论(0编辑  收藏  举报