leetcode周赛 - 406

100352. 交换后字典序最小的字符串

  给你一个仅由数字组成的字符串 s,在最多交换一次 相邻 且具有相同 奇偶性 的数字后,返回可以得到的字典序最小的字符串。

  如果两个数字都是奇数或都是偶数,则它们具有相同的奇偶性。例如,5 和 9、2 和 4 奇偶性相同,而 6 和 9 奇偶性不同。

思路

  从左到右扫一遍就行,交换的越早越好,因为字典序是从左往右看的

import java.util.Arrays;

class Solution {
    public String getSmallestString(String s) {
        char[] charArray = s.toCharArray();
        for (int i = 0; i < charArray.length - 1; i++) {
            int now = charArray[i] - '0', nxt = charArray[i + 1] - '0';
            if (now % 2 == nxt % 2 && now > nxt) {
                char tmp = charArray[i];
                charArray[i] = charArray[i + 1];
                charArray[i + 1] = tmp;
                break;
            }
        }
        return new String(charArray);
    }
}

100368. 从链表中移除在数组中存在的节点

  给你一个整数数组 nums 和一个链表的头节点 head。从链表中移除所有存在于 nums 中的节点后,返回修改后的链表的头节点。

思路

  将nums转成一个set,就能在O(1)的时间内判断当前节点值在不在nums里,然后扫一遍维护指针就行

  当然还有一种方法是记录那些没在nums里的节点值,重新做一个链表出来返回

import java.util.HashSet;
import java.util.Set;
class Solution {
    public ListNode modifiedList(int[] nums, ListNode head) {
        if (head == null) return null;
        Set<Integer> set = new HashSet<>();
        for (int num : nums) {
            set.add(num);
        }
        ListNode newHead = head;
        while (newHead != null && set.contains(newHead.val)) newHead = newHead.next;
        if (newHead == null) return null;
        ListNode pre = newHead;
        while (pre.next != null) {
            ListNode now = pre.next;
            if (set.contains(now.val)) {
                pre.next = findNewNextNode(set, now);
                if (pre.next != null) pre = pre.next;
                continue;
            }
            pre = now;
        }
        return newHead;
    }

    private ListNode findNewNextNode(Set<Integer> set, ListNode now) {
        ListNode ans = now;
        while (set.contains(ans.val)) {
            ans = ans.next;
            if (ans == null) break;
        }
        return ans;
    }
}

100361. 切蛋糕的最小总开销 I

有一个 m x n 大小的矩形蛋糕,需要切成 1 x 1 的小块。

给你整数 m ,n 和两个数组:

  • horizontalCut 的大小为 m - 1 ,其中 horizontalCut[i] 表示沿着水平线 i 切蛋糕的开销。
  • verticalCut 的大小为 n - 1 ,其中 verticalCut[j] 表示沿着垂直线 j 切蛋糕的开销。

一次操作中,你可以选择任意不是 1 x 1 大小的矩形蛋糕并执行以下操作之一:

  1. 沿着水平线 i 切开蛋糕,开销为 horizontalCut[i] 。
  2. 沿着垂直线 j 切开蛋糕,开销为 verticalCut[j] 。

每次操作后,这块蛋糕都被切成两个独立的小蛋糕。

每次操作的开销都为最开始对应切割线的开销,并且不会改变。

请你返回将蛋糕全部切成 1 x 1 的蛋糕块的 最小 总开销。

思路

  当你横着切一刀时,竖着切时都要加一刀,竖着切同理,所以我们想每次切大的花费的边,这样就不会重复切多次。把横边和竖边降序排序,维护两个多切系数,每次选择横边和竖边较大的那边来切,同时维护多切系数,横的切一刀,竖边的多切系数就要+1,反之同理

import java.util.Arrays;

class Solution {
    public static int minimumCost(int m, int n, int[] horizontalCut, int[] verticalCut) {
        int cos = 0;
        int horizonNum = 1, verticalNum = 1;
        reverseOrderQuickSort(horizontalCut, 0, horizontalCut.length - 1);
        reverseOrderQuickSort(verticalCut, 0, verticalCut.length - 1);
        int i = 0, j = 0;
        while (i < horizontalCut.length || j < verticalCut.length) {
            if (i == horizontalCut.length) {
                cos += verticalCut[j] * verticalNum;
                j++;
                continue;
            }
            if (j == verticalCut.length) {
                cos += horizontalCut[i] * horizonNum;
                i++;
                continue;
            }
            if (horizontalCut[i] > verticalCut[j]) {
                cos += horizontalCut[i] * horizonNum;
                verticalNum++;
                i++;
            } else {
                cos += verticalCut[j] * verticalNum;
                horizonNum++;
                j++;
            }
        }
        return cos;
    }

    private static void reverseOrderQuickSort(int[] num, int left, int right) {
        if (left < right) {
            int i = left, j = right, n = num[left];
            while (i < j) {
                while (i < j && num[j] <= n) j--;
                if (i < j) num[i++] = num[j];
                while (i < j && num[i] > n) i++;
                if (i < j) num[j--] = num[i];
            }
            num[i] = n;
            reverseOrderQuickSort(num, left, i - 1);
            reverseOrderQuickSort(num, i + 1, right);
        }
    }
}

100367. 切蛋糕的最小总开销 II

  题意和刚刚一样,在刚刚的基础上增大n和m的数据量

思路

  和第三题是一样的,我的解法tle了,时间复杂度应该是一样的,问题应该是手写的快排没有jdk的速度快,用jdk的api就能AC

import java.util.Arrays;

class Solution {
    public long minimumCost(int m, int n, int[] horizontalCut, int[] verticalCut) {
        long cos = 0;
        int horizonNum = 1, verticalNum = 1;
        Arrays.sort(horizontalCut);
        Arrays.sort(verticalCut);
        int i = horizontalCut.length - 1, j = verticalCut.length - 1;
        while (i >= 0 || j >= 0) {
            if (j < 0 || i >= 0 && horizontalCut[i] > verticalCut[j]) {
                cos += (long) horizontalCut[i] * horizonNum;
                verticalNum++;
                i--;
            } else {
                cos += (long) verticalCut[j] * verticalNum;
                horizonNum++;
                j--;
            }
        }
        return cos;
    }
}

 

posted @ 2024-07-14 23:45  艾尔夏尔-Layton  阅读(9)  评论(0编辑  收藏  举报