LeetCode第223场周赛

LeetCode第223场周赛

题目:1720. 解码异或后的数组

未知 整数数组 arr 由 n 个非负整数组成。

经编码后变为长度为 n - 1 的另一个整数数组 encoded ,其中 encoded[i] = arr[i] XOR arr[i + 1] 。例如,arr = [1,0,2,1] 经编码后得到 encoded = [1,2,3] 。

给你编码后的数组 encoded 和原数组 arr 的第一个元素 first(arr[0])。

请解码返回原数组 arr 。可以证明答案存在并且是唯一的。

示例 1:

输入:encoded = [1,2,3], first = 1
输出:[1,0,2,1]
解释:若 arr = [1,0,2,1] ,那么 first = 1 且 encoded = [1 XOR 0, 0 XOR 2, 2 XOR 1] = [1,2,3]
示例 2:

输入:encoded = [6,2,7,3], first = 4
输出:[4,2,0,7,4]

提示:

2 <= n <= 104
encoded.length == n - 1
0 <= encoded[i] <= 105
0 <= first <= 105

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/decode-xored-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

代码:简单模拟

简单模拟之前,我们需要知道两个相同的数字的异或和等于0;

class Solution {
    public int[] decode(int[] encoded, int first) {
        int n = encoded.length;
        int[] arr = new int[n + 1];
        arr[0] = first;
        for(int i = 1; i <= n; i++){
            arr[i] = arr[i - 1] ^ encoded[i - 1];
        }
        return arr;
    }
}

题目:1721. 交换链表中的节点

给你链表的头节点 head 和一个整数 k 。

交换 链表正数第 k 个节点和倒数第 k 个节点的值后,返回链表的头节点(链表 从 1 开始索引)。

示例 1:

输入:head = [1,2,3,4,5], k = 2
输出:[1,4,3,2,5]
示例 2:

输入:head = [7,9,6,6,7,8,3,0,9,5], k = 5
输出:[7,9,6,6,8,7,3,0,9,5]
示例 3:

输入:head = [1], k = 1
输出:[1]
示例 4:

输入:head = [1,2], k = 1
输出:[2,1]
示例 5:

输入:head = [1,2,3], k = 2
输出:[1,2,3]

提示:

链表中节点的数目是 n
1 <= k <= n <= 105
0 <= Node.val <= 100

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/swapping-nodes-in-a-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

代码:快慢指针

简单的做法是直接将整个链表用数组保存下来,然后在数组里进行交换。

而在链表中,找前后k位:

  • 找前k位遍历的时候记录一下走到第几位了即可。
  • 找后k位,先让一个指针先走k位,然后再用一个指针从头开始走,当先走的指针走到走到最后一个时,慢走的指针就在后k位的位置。
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode swapNodes(ListNode head, int k) {
        ListNode ans = new ListNode(0);
        ans.next = head;
        int n = 0;
        for(ListNode q = head; q != null; q = q.next) n++;
        if(k > (n + 1) / 2) k = n - k + 1;

        ListNode p = head, lq = ans;
        for(int i = 1; i < k; i++) {
            lq = p;
            p = p.next;
        }
        ListNode lk = p, rq = ans;
        while(p.next != null) {
            p = p.next;
            rq = head;
            head = head.next;
        }
        rq.next = lk;
        p = lk.next;
        lk.next = head.next;
        lq.next = head;
        head.next = p;
        return ans.next;
    }
}

题目:1722. 执行交换操作后的最小汉明距离

给你两个整数数组 source 和 target ,长度都是 n 。还有一个数组 allowedSwaps ,其中每个 allowedSwaps[i] = [ai, bi] 表示你可以交换数组 source 中下标为 ai 和 bi(下标从 0 开始)的两个元素。注意,你可以按 任意 顺序 多次 交换一对特定下标指向的元素。

相同长度的两个数组 source 和 target 间的 汉明距离 是元素不同的下标数量。形式上,其值等于满足 source[i] != target[i] (下标从 0 开始)的下标 i(0 <= i <= n-1)的数量。

在对数组 source 执行 任意 数量的交换操作后,返回 source 和 target 间的 最小汉明距离 。

示例 1:

输入:source = [1,2,3,4], target = [2,1,4,5], allowedSwaps = [[0,1],[2,3]]
输出:1
解释:source 可以按下述方式转换:

  • 交换下标 0 和 1 指向的元素:source = [2,1,3,4]
  • 交换下标 2 和 3 指向的元素:source = [2,1,4,3]
    source 和 target 间的汉明距离是 1 ,二者有 1 处元素不同,在下标 3 。
    示例 2:

输入:source = [1,2,3,4], target = [1,3,2,4], allowedSwaps = []
输出:2
解释:不能对 source 执行交换操作。
source 和 target 间的汉明距离是 2 ,二者有 2 处元素不同,在下标 1 和下标 2 。
示例 3:

输入:source = [5,1,2,4,3], target = [1,5,4,2,3], allowedSwaps = [[0,4],[4,2],[1,3],[1,4]]
输出:0

提示:

n == source.length == target.length
1 <= n <= 105
1 <= source[i], target[i] <= 105
0 <= allowedSwaps.length <= 105
allowedSwaps[i].length == 2
0 <= ai, bi <= n - 1
ai != bi

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimize-hamming-distance-after-swap-operations
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

代码:并查集

class Solution {
    int[] f;
    public int find(int x){
        if(x == f[x]) return x;
        return f[x] = find(f[x]);
    }
    public int minimumHammingDistance(int[] source, int[] target, int[][] swap) {
        int m = swap.length, n = source.length, ans = 0;
        f = new int[n];
        for(int i = 0; i < n; i++) f[i] = i;
        for(int i = 0; i < m; i++) {
            f[find(swap[i][0])] = find(swap[i][1]);
        }

        HashMap<Integer, Integer>[] h = new HashMap[n];
        for(int i = 0; i < n; i++) {
            int f = find(i);
            if(h[f] == null) h[f] = new HashMap<>();
            h[f].put(source[i], h[f].getOrDefault(source[i], 0) + 1);
        }
        for(int i = 0; i < n; i++) {
            HashMap<Integer, Integer> ch = h[find(i)];
            if(ch.containsKey(target[i])){
                int cnt = ch.get(target[i]);
                if(cnt == 1){
                    ch.remove(target[i]);
                }else{
                    ch.put(target[i], cnt - 1);
                }
            }else{
                ans++;
            }
        }
        return ans;
    }
}

题目:1723. 完成所有工作的最短时间

给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i 项工作要花费的时间。

请你将这些工作分配给 k 位工人。所有工作都应该分配给工人,且每项工作只能分配给一位工人。工人的 工作时间 是完成分配给他们的所有工作花费时间的总和。请你设计一套最佳的工作分配方案,使工人的 最大工作时间 得以 最小化 。

返回分配方案中尽可能 最小 的 最大工作时间 。

示例 1:

输入:jobs = [3,2,3], k = 3
输出:3
解释:给每位工人分配一项工作,最大工作时间是 3 。
示例 2:

输入:jobs = [1,2,4,7,8], k = 2
输出:11
解释:按下述方式分配工作:
1 号工人:1、2、8(工作时间 = 1 + 2 + 8 = 11)
2 号工人:4、7(工作时间 = 4 + 7 = 11)
最大工作时间是 11 。

提示:

1 <= k <= jobs.length <= 12
1 <= jobs[i] <= 107

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-minimum-time-to-finish-all-jobs
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

代码:dfs+简单剪枝

class Solution {
    int ans = Integer.MAX_VALUE;
    int[] f;
    public int minimumTimeRequired(int[] jobs, int k) {
        int n = jobs.length;
        f = new int[k];
        dfs(0, jobs, 0, 0);
        return ans;
    }

    private void dfs(int k, int[] j, int max, int idx) {
        if(max > ans) return;
        if(k == j.length){
            ans = Math.min(max, ans);
            return;
        }
        for(int i = 0; i < idx; i++){
            f[i] += j[k];
            dfs(k + 1, j, Math.max(max, f[i]), idx);
            f[i] -= j[k];
        }
        if(idx < f.length){
            f[idx] = j[k];
            dfs(k + 1, j, Math.max(max, f[idx]), idx + 1);
            f[idx] = 0;
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值