第22场双周赛

应该有三个多月没有参加周赛,今天参加下双周赛,第一局傻了,居然把10的3次方看成300,导致两次错误,第二题没在意n特别大,第三题结束,暂时排名一百多,很慌,第四局想了一会,突然灵光一闪,代码实现,一次通过。
先说下总结:
1、很重要的提示,数组的数值范围很小,那就很简单了,先把arr2的数字放到数组里,然后再让arr1比比较
2、如果只判断一排的座位,那是简单的,那就把所有的按排进行分类,一排一排分析呗
3、这道题,我就是把每个数字的权重找到,然后排序的
4、这题的开始觉得这不得一次一次试,立马被推翻了,突然灵光一闪,那不就是不能有任意两个数相邻嘛,然后用上最优规划,注意了细节(首位和末位不能同时被选中),然后,答案就出来了。爽。
哈哈哈,第十九名,要不是第一题失误,就是第十四名了。

两个数组间的距离值
给你两个整数数组 arr1 , arr2 和一个整数 d ,请你返回两个数组之间的 距离值 。
「距离值」 定义为符合此描述的元素数目:对于元素 arr1[i] ,不存在任何元素 arr2[j] 满足 |arr1[i]-arr2[j]| <= d 。

示例 1:

输入:arr1 = [4,5,8], arr2 = [10,9,1,8], d = 2
输出:2
解释:
对于 arr1[0]=4 我们有:
|4-10|=6 > d=2
|4-9|=5 > d=2
|4-1|=3 > d=2
|4-8|=4 > d=2
对于 arr1[1]=5 我们有:
|5-10|=5 > d=2
|5-9|=4 > d=2
|5-1|=4 > d=2
|5-8|=3 > d=2
对于 arr1[2]=8 我们有:
|8-10|=2 <= d=2
|8-9|=1 <= d=2
|8-1|=7 > d=2
|8-8|=0 <= d=2

示例 2:
输入:arr1 = [1,4,2,3], arr2 = [-4,-3,6,10,20,30], d = 3
输出:2

示例 3:
输入:arr1 = [2,1,100,3], arr2 = [-5,-2,10,-3,7], d = 6
输出:1

提示:
1 <= arr1.length, arr2.length <= 500
-10^3 <= arr1[i], arr2[j] <= 10^3
0 <= d <= 100

解答:

public int findTheDistanceValue(int[] arr1, int[] arr2, int d) {
    int[] values = new int[2001];
    for (int i = 0; i < arr2.length; i++) {
        values[arr2[i] + 1000]++;
    }
    int ans = arr1.length;
    for (int i = 0; i < arr1.length; i++) {
        for (int j = Math.max(0, arr1[i] + 1000 - d); j <= Math.min(2000, arr1[i] + 1000 + d); j++) {
            if (values[j] > 0) {
                ans--;
                break;
            }
        }
    }
    return ans;
}

安排电影院座位
电影院的观影厅中有 n 行座位,行编号从 1 到 n ,且每一行内总共有 10 个座位,列编号从 1 到 10 。
给你数组 reservedSeats ,包含所有已经被预约了的座位。比如说,researvedSeats[i]=[3,8] ,它表示第 3 行第 8 个座位被预约了。
请你返回 最多能安排多少个 4 人家庭 。4 人家庭要占据 同一行内连续 的 4 个座位。隔着过道的座位(比方说 [3,3] 和 [3,4])不是连续的座位,但是如果你可以将 4 人家庭拆成过道两边各坐 2 人,这样子是允许的。

示例 1:
输入:n = 3, reservedSeats = [[1,2],[1,3],[1,8],[2,6],[3,1],[3,10]]
输出:4
解释:上图所示是最优的安排方案,总共可以安排 4 个家庭。蓝色的叉表示被预约的座位,橙色的连续座位表示一个 4 人家庭。

示例 2:
输入:n = 2, reservedSeats = [[2,1],[1,8],[2,6]]
输出:2

示例 3:
输入:n = 4, reservedSeats = [[4,3],[1,4],[4,6],[1,7]]
输出:4

提示:
1 <= n <= 10^9
1 <= reservedSeats.length <= min(10*n, 10^4)
reservedSeats[i].length == 2
1 <= reservedSeats[i][0] <= n
1 <= reservedSeats[i][1] <= 10
所有 reservedSeats[i] 都是互不相同的。

解答:

public int maxNumberOfFamilies(int n, int[][] reservedSeats) {
    if (n > 10000) {
        return getMax(n, reservedSeats);
    }
	//对,这就是我之前的答案,忘了考虑n特大了
    boolean[][] vlues = new boolean[n + 1][11];
    for (int[] kk : reservedSeats) {
        vlues[kk[0]][kk[1]] = true;
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        if (check(vlues, 2, 5, i)) {
            ans++;
            if (check(vlues, 6, 9, i)) {
                ans++;
            }
        } else {
            if (check(vlues, 4, 7, i)) {
                ans++;
            } else {
                if (check(vlues, 6, 9, i)) {
                    ans++;
                }
            }
        }
    }
    return ans;
}

private boolean check(boolean[][] vlues, int sta, int end, int k) {
    for (int i = sta; i <= end; i++) {
        if (vlues[k][i]) {
            return false;
        }
    }
    return true;
}

private int getMax(int n, int[][] reservedSeats) {
    Map maps = new HashMap<>();
    for (int[] kk : reservedSeats) {
        boolean[] kkk = maps.get(kk[0]);
        if (kkk == null) {
            kkk = new boolean[11];
            maps.put(kk[0], kkk);
        }
        kkk[kk[1]] = true;
    }
    int ans = 2 * n;
    for (boolean[] vlues : maps.values()) {
        ans -= 2;
        if (check(vlues, 2, 5)) {
            ans++;
            if (check(vlues, 6, 9)) {
                ans++;
            }
        } else {
            if (check(vlues, 4, 7)) {
                ans++;
            } else {
                if (check(vlues, 6, 9)) {
                    ans++;
                }
            }
        }
    }
    return ans;
}

private boolean check(boolean[] vlues, int sta, int end) {
    for (int i = sta; i <= end; i++) {
        if (vlues[i]) {
            return false;
        }
    }
    return true;
}

将整数按权重排序
我们将整数 x 的 权重 定义为按照下述规则将 x 变成 1 所需要的步数:
如果 x 是偶数,那么 x = x / 2
如果 x 是奇数,那么 x = 3 * x + 1

比方说,x=3 的权重为 7 。因为 3 需要 7 步变成 1 (3 --> 10 --> 5 --> 16 --> 8 --> 4 --> 2 --> 1)。
给你三个整数 lo, hi 和 k 。你的任务是将区间 [lo, hi] 之间的整数按照它们的权重 升序排序 ,如果大于等于 2 个整数有 相同 的权重,那么按照数字自身的数值 升序排序 。
请你返回区间 [lo, hi] 之间的整数按权重排序后的第 k 个数。
注意,题目保证对于任意整数 x (lo <= x <= hi) ,它变成 1 所需要的步数是一个 32 位有符号整数。

示例 1:
输入:lo = 12, hi = 15, k = 2
输出:13
解释:12 的权重为 9(12 --> 6 --> 3 --> 10 --> 5 --> 16 --> 8 --> 4 --> 2 --> 1)
13 的权重为 9
14 的权重为 17
15 的权重为 17
区间内的数按权重排序以后的结果为 [12,13,14,15] 。对于 k = 2 ,答案是第二个整数也就是 13 。
注意,12 和 13 有相同的权重,所以我们按照它们本身升序排序。14 和 15 同理。

示例 2:
输入:lo = 1, hi = 1, k = 1
输出:1

示例 3
输入:lo = 7, hi = 11, k = 4
输出:7
解释:区间内整数 [7, 8, 9, 10, 11] 对应的权重为 [16, 3, 19, 6, 14] 。
按权重排序后得到的结果为 [8, 10, 11, 7, 9] 。
排序后数组中第 4 个数字为 7 。

示例 4:
输入:lo = 10, hi = 20, k = 5
输出:13

示例 5:
输入:lo = 1, hi = 1000, k = 777
输出:570

提示:
1 <= lo <= hi <= 1000
1 <= k <= hi - lo + 1

解答:

public int getKth(int lo, int hi, int k) {
    List nodes = new ArrayList<>();
     for (int i = lo; i <= hi; i++) {
        Node node = new Node();
        node.key = getKey(i);
        node.value = i;
        nodes.add(node);
    }
    Collections.sort(nodes, new Comparator() {
        @Override
        public int compare(Node o1, Node o2) {
            if (o1.key == o2.key) {
                return o1.value - o2.value;
            }
            return o1.key - o2.key;
        }
    });
    return nodes.get(k - 1).value;
}

Map keyvalues = new HashMap<>();

private int getKey(int k) {
    if (k == 1) {
        return 0;
    }
    if (keyvalues.containsKey(k)) {
        return keyvalues.get(k);
    }
    int ans = 0;
    if (k % 2 == 0) {

        ans = 1 + getKey(k / 2);
    } else {
        ans = 1 + getKey(3 * k + 1);
    }
    keyvalues.put(k, ans);
    return ans;
}

class Node {
    int value;
    int key;
}

3n 块披萨

给你一个披萨,它由 3n 块不同大小的部分组成,现在你和你的朋友们需要按照如下规则来分披萨:
你挑选 任意 一块披萨。
Alice 将会挑选你所选择的披萨逆时针方向的下一块披萨。
Bob 将会挑选你所选择的披萨顺时针方向的下一块披萨。
重复上述过程直到没有披萨剩下。
每一块披萨的大小按顺时针方向由循环数组 slices 表示。
请你返回你可以获得的披萨大小总和的最大值。

示例 1:
输入:slices = [1,2,3,4,5,6]
输出:10
解释:选择大小为 4 的披萨,Alice 和 Bob 分别挑选大小为 3 和 5 的披萨。然后你选择大小为 6 的披萨,Alice 和 Bob 分别挑选大小为 2 和 1 的披萨。你获得的披萨总大小为 4 + 6 = 10 。

示例 2:
输入:slices = [8,9,8,6,1,1]
输出:16
解释:两轮都选大小为 8 的披萨。如果你选择大小为 9 的披萨,你的朋友们就会选择大小为 8 的披萨,这种情况下你的总和不是最大的。

示例 3:
输入:slices = [4,1,2,5,8,3,1,9,7]
输出:21

示例 4:
输入:slices = [3,1,2]
输出:3

提示:
1 <= slices.length <= 500
slices.length % 3 == 0
1 <= slices[i] <= 1000

解答:

public int maxSizeSlices(int[] slices) {
    return Math.max(getOne(slices), notGetOne(slices));

}

public int getOne(int[] slices) {
    int ans = slices[0];
    int len = slices.length;
    int[][] res = new int[len + 1][len / 3 + 1];
    res[1][1] = ans;
    for (int i = 2; i <= len - 1; i++) {
        for (int j = 1; j <= Math.min((i + 2) / 2, len / 3); j++) {
            res[i][j] = Math.max(slices[i - 1] + res[i - 2][j - 1], res[i - 1][j]);
        }
    }
    return res[len - 1][len / 3];
}

public int notGetOne(int[] slices) {
    int len = slices.length;
    int[][] res = new int[len + 1][len / 3 + 1];
    res[2][1] = slices[1];
    for (int i = 2; i <= len; i++) {
        for (int j = 1; j <= Math.min((i + 2) / 2, len / 3); j++) {
            res[i][j] = Math.max(slices[i - 1] + res[i - 2][j - 1], res[i - 1][j]);
        }
    }
    return res[len][len / 3];

}

你可能感兴趣的:(leetcode,算法)