Leetcode刷题记录

通过

/**
 * 你正在经营一座摩天轮,该摩天轮共有 4 个座舱 ,每个座舱 最多可以容纳 4 位游客 。你可以 逆时针 轮转座舱,但每次轮转都需要支付一定的运行成本 runningCost 。
 * 给你一个长度为 n 的数组 customers , customers[i] 是在第 i 次轮转(下标从 0 开始)之前到达的新游客的数量。这也意味着你必须在新游客到来前轮转 i 次。如果有座舱空闲就不能让游客等待。每位游客在登上离地面最近的座舱前都会支付登舱成本 boardingCost ,一旦该座舱再次抵达地面,他们就会离开座舱结束游玩。
 * 你可以随时停下摩天轮,即便是 在服务所有游客之前 。如果你决定停止运营摩天轮,为了保证所有游客安全着陆,将免费进行所有后续轮转 。注意,如果有超过 4 位游客在等摩天轮,那么只有 4 位游客可以登上摩天轮,其余的需要等待 下一次轮转 。
 * 返回最大化利润所需执行的 最小轮转次数 。 如果不存在利润为正的方案,则返回 -1 。
 * @since 2024/5/27
 */
public class Code1599 {
    public static int minOperationsMaxProfit(int[] customers, int boardingCost, int runningCost) {
        int profit = 0;
        int maxProfit = 0;
        int maxNumber = -1;
        int remain = 0;
        for (int i = 0; i <= customers.length - 1 || remain > 0; i++) {
            if (i <= customers.length - 1) {
                remain += customers[i];
            }

            if (remain <= 4) {
                profit += remain * boardingCost - runningCost;
                remain = 0;
            } else {
                profit += 4 * boardingCost - runningCost;
                remain -= 4;
            }
            if (profit > maxProfit) {
                maxProfit = profit;
                maxNumber = i + 1;
            }
        }
        return maxNumber;
    }

    public static void main(String[] args) {
        int[] customers = new int[]{8, 3};
        int boardingCost = 5;
        int runningCost = 6;
        System.out.println(minOperationsMaxProfit(customers, boardingCost, runningCost));
    }
}
/**
 * 现有一份 n + m 次投掷单个 六面 骰子的观测数据,骰子的每个面从 1 到 6 编号。观测数据中缺失了 n 份,你手上只拿到剩余 m 次投掷的数据。幸好你有之前计算过的这 n + m 次投掷数据的 平均值 。
 * 给你一个长度为 m 的整数数组 rolls ,其中 rolls[i] 是第 i 次观测的值。同时给你两个整数 mean 和 n 。
 * 返回一个长度为 n 的数组,包含所有缺失的观测数据,且满足这 n + m 次投掷的 平均值 是 mean 。如果存在多组符合要求的答案,只需要返回其中任意一组即可。如果不存在答案,返回一个空数组。
 * k 个数字的 平均值 为这些数字求和后再除以 k 。
 * 注意 mean 是一个整数,所以 n + m 次投掷的总和需要被 n + m 整除。
 * @since 2024/5/27
 */

import java.util.Arrays;

public class Code2028 {
    public static int[] missingRolls(int[] rolls, int mean, int n) {
        int sum = 0;
        for (int i : rolls) {
            sum += i;
        }
        int remain = (rolls.length + n) * mean - sum - n;
        if (remain < 0 || remain > 5 * n) {
            return new int[0];
        }
        int[] rolls2 = new int[n];
        Arrays.fill(rolls2, 1);
        for (int i = 0; i <= rolls2.length - 1; i++) {
            if (remain <= 5) {
                rolls2[i] = remain + 1;
                return rolls2;
            } else {
                rolls2[i] = 6;
                remain -= 5;
            }
        }

        return rolls2;
    }

    public static void main(String[] args) {
        int[] rolls = new int[]{3, 2, 4, 3};
        int mean = 4;
        int n = 2;
        System.out.println(Arrays.toString(missingRolls(rolls, mean, n)));
    }
}
/**
 * 给你一个长度为 n 的二维整数数组 items 和一个整数 k 。
 * items[i] = [profiti, categoryi],其中 profiti 和 categoryi 分别表示第 i 个项目的利润和类别。
 * 现定义 items 的 子序列 的 优雅度 可以用 total_profit + distinct_categories2 计算,其中 total_profit 是子序列中所有项目的利润总和,
 * distinct_categories 是所选子序列所含的所有类别中不同类别的数量。
 * 你的任务是从 items 所有长度为 k 的子序列中,找出 最大优雅度 。
 * 用整数形式表示并返回 items 中所有长度恰好为 k 的子序列的最大优雅度。
 * 注意:数组的子序列是经由原数组删除一些元素(可能不删除)而产生的新数组,且删除不改变其余元素相对顺序。
 * @since 2024/6/26
 */

import java.util.*;

public class Code2813_2 {

    public static long findMaximumElegance(int[][] items, int k) {
        Arrays.sort(items, (item0, item1) -> (item1[0] - item0[0]));
        long profit = 0;
        long elegance = Long.MIN_VALUE;
        Set<Integer> categorySet = new HashSet<>();
        ArrayDeque<Integer> repeatedItems = new ArrayDeque<>();
        for (int i = 0; i <= items.length - 1; i++) {
            if (i < k) {
                profit += items[i][0];
                if (!categorySet.add(items[i][1])) {
                    repeatedItems.push(items[i][0]);
                }
            } else {
                if (!repeatedItems.isEmpty() && categorySet.add(items[i][1])) {
                    profit = profit - repeatedItems.pop() + items[i][0];
                    elegance = Math.max(elegance, profit + (long) categorySet.size() * categorySet.size());
                }
            }

            if (i == k - 1) {
                elegance = profit + (long) categorySet.size() * categorySet.size();
            }
        }
        return elegance;
    }

    public static void main(String[] args) {
        int[][] items = new int[3][2];
        items[0][0] = 1;
        items[0][1] = 2;
        items[1][0] = 10;
        items[1][1] = 1;
        System.out.println(findMaximumElegance(items, 1));
    }
}
/**
 * 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
 * @since 2024/6/28
 */
public class Code206 {
    public static void main(String[] args) {
        ListNode node1 = new ListNode(1);
        ListNode node2 = new ListNode(2);
        ListNode node3 = new ListNode(3);
        ListNode node4 = new ListNode(4);
        ListNode node5 = new ListNode(5);
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        node5.next = null;
        ListNode node = reverseList(node1);
        while (node != null) {
            System.out.print(node.val + "\t");
            node = node.next;
        }
    }

    public static ListNode reverseList2(ListNode head) {
        ListNode pre = null;
        ListNode next = null;
        while (head != null) {
            next = head.next;
            head.next = pre;
            pre = head;
            head = next;
        }
        return pre;
    }

    public static ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode newHead = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return newHead;
    }


    public static class ListNode {
      int val;
      ListNode next;
      ListNode() {}
      ListNode(int val) { this.val = val; }
      ListNode(int val, ListNode next) { this.val = val; this.next = next; }
  }
}
/**
 * 给定两个单链表的头节点 headA 和 headB ,请找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
 * @since 2024/6/28
 */
public class CodeLCR023 {
    public static void main(String[] args) {
        ListNode node1 = new ListNode(1);
        ListNode node2 = new ListNode(2);
        ListNode node3 = new ListNode(3);
        ListNode node4 = new ListNode(4);
        ListNode node5 = new ListNode(5);
        node1.next = node2;
        node2.next = node3;
        node3.next = null;
        node4.next = node5;
        node5.next = node3;
        ListNode node = getIntersectionNode(node1, node4);
        System.out.println(node.val);
    }

    public static ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode node = headB;
        while (headA != null) {
            while(headB != null) {
                if (headA == headB) {
                    return headA;
                }
                headB = headB.next;
            }
            headB = node;
            headA = headA.next;
        }
        return null;
    }

    public static class ListNode {
      int val;
      ListNode next;
      ListNode(int x) {
          val = x;
          next = null;
      }
  }
}
/**
 * 给你一个链表的头节点 head ,判断链表中是否有环。
 * 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
 * 如果链表中存在环 ,则返回 true 。 否则,返回 false 。
 * @since 2024/6/29
 */

import java.util.HashSet;
import java.util.Set;

public class Code141 {
    public static void main(String[] args) {
        ListNode node1 = new ListNode(1);
        ListNode node2 = new ListNode(2);
        node1.next = node2;
        node2.next = node1;
        System.out.println(hasCycle(node1));
    }

    public static boolean hasCycle(ListNode head) {
        ListNode node = head;
        Set<ListNode> nodeSet = new HashSet<>();
        while (node != null) {
            if (!nodeSet.add(node)) {
                return true;
            }
            node = node.next;
        }
        return false;
    }

    static class ListNode {
      int val;
      ListNode next;
      ListNode(int x) {
          val = x;
          next = null;
      }
   }
}
/**
 * 给你一个非负整数数组 nums 和一个整数 target 。
 * 向数组中的每个整数前添加 '+' 或 '-' ,然后串联起所有整数,可以构造一个 表达式 :
 * 例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1" 。
 * 返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。
 * @since 2024/6/30
 */
public class Code494 {

    public static int ways = 0;

    public static void main(String[] args) {
        int[] nums = {1, 1, 1, 1, 1};
        System.out.println(findTargetSumWays(nums, 3));
    }

    public static int findTargetSumWays(int[] nums, int target) {
        find(nums, target, 0);
        return ways;
    }

    public static void find(int[] nums, int target, int index) {
        if (index == nums.length) {
            if (target == 0) {
                ways++;
            }
            return;
        }

        find(nums, target + nums[index], index + 1);
        find(nums, target - nums[index], index + 1);
    }
}
/**
 * 给定一个可能有重复数字的整数数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
 * candidates 中的每个数字在每个组合中只能使用一次,解集不能包含重复的组合。
 * @since 2024/7/2
 */

import java.util.*;

public class CodeLCR081 {

    public static Set<List<Integer>> result = new HashSet<>();

    public static List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        combine(candidates, target, new ArrayList<>(), 0);
        return new ArrayList<>(result);
    }

    public static void combine(int[] candidates, int target, List<Integer> combination, int index) {
        if (target < 0) {
            return;
        }

        if (target == 0) {
            List<Integer> comb = new ArrayList<>(combination);
            result.add(comb);
            return;
        }

        if (index == candidates.length) {
            return;
        }

        combine(candidates, target, combination, index + 1);
        combination.add(candidates[index]);
        combine(candidates, target - candidates[index], combination, index + 1);
        combination.remove(combination.size() - 1);
    }

    public static void main(String[] args) {
        int[] candidates = new int[]{10, 1, 2, 7, 6, 1, 5};
        System.out.println(combinationSum2(candidates, 8));
    }
}
/**
 * 给定一个不含重复数字的整数数组 nums ,返回其 所有可能的全排列 。可以 按任意顺序 返回答案。
 * @since 2024/7/3
 */

import java.util.ArrayList;
import java.util.List;

public class CodeLCR083 {

    public static List<List<Integer>> result = new ArrayList<>();

    public static List<List<Integer>> permute(int[] nums) {
        range(nums, 0, new ArrayList<>());
        return result;
    }

    public static void range(int[] nums, int index, List<Integer> permutation) {
        if (index == nums.length) {
            result.add(new ArrayList<>(permutation));
        }

        for (int i = 0; i <= nums.length - 1; i++) {
            if (!permutation.contains(nums[i])) {
                permutation.add(nums[i]);
                range(nums, index + 1, permutation);
                permutation.remove(permutation.size() - 1);
            }
        }
    }

    public static void main(String[] args) {
        System.out.println(permute(new int[]{1, 2, 3}));
    }
}
/**
 * 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
 * 请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
 * 注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
 * @since 2024/7/3
 */

public class Code88 {
    public static void merge(int[] nums1, int m, int[] nums2, int n) {
        int[] result = new int[m + n];
        int i = 0;
        int j = 0;
        for (int k = 0; k <= m + n - 1; k++) {
            if (i == m) {
                result[k] = nums2[j];
                j++;
                continue;
            }

            if (j == n) {
                result[k] = nums1[i];
                i++;
                continue;
            }

            if (nums1[i] > nums2[j]) {
                result[k] = nums2[j];
                j++;
            } else {
                result[k] = nums1[i];
                i++;
            }
        }
        System.arraycopy(result, 0, nums1, 0, nums1.length);
    }

    public static void main(String[] args) {
        int[] nums1 = new int[]{1, 2, 3, 0, 0, 0};
        int[] nums2 = new int[]{2, 5, 6};
        merge(nums1, 3, nums2, 3);
    }
}
    /**
     * 36.有效的数独
     * 请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。
     * 数字 1-9 在每一行只能出现一次。
     * 数字 1-9 在每一列只能出现一次。
     * 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
     * 注意:
     * 一个有效的数独(部分已被填充)不一定是可解的。
     * 只需要根据以上规则,验证已经填入的数字是否有效即可。
     * 空白格用 '.' 表示。
     * @since 2024/7/4
     */
    public boolean isValidSudoku(char[][] board) {
        Set<Character> numSet = new HashSet<>();
        for (int i = 0; i <= 8; i++) {
            numSet.clear();
            for (int j = 0; j <= 8; j++) {
                char c = board[i][j];
                if (c != '.') {
                    if (!numSet.add(c)) {
                        return false;
                    }
                }
            }
        }

        for (int i = 0; i <= 8; i++) {
            numSet.clear();
            for (int j = 0; j <= 8; j++) {
                char c = board[j][i];
                if (c != '.') {
                    if (!numSet.add(c)) {
                        return false;
                    }
                }
            }
        }

        for (int k = 0; k <= 2; k++) {
            for (int m = 0; m <= 2; m++) {
                numSet.clear();
                for (int i = 3 * k; i <= 3 * k + 2; i++) {
                    for (int j = 3 * m; j <= 3 * m + 2; j++) {
                        char c = board[i][j];
                        if (c != '.') {
                            if (!numSet.add(c)) {
                                return false;
                            }
                        }
                    }
                }
            }
        }

        return true;
    }
/**
 * 给定两个 非空链表 l1和 l2 来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
 * 可以假设除了数字 0 之外,这两个数字都不会以零开头。
 */
public class CodeLCR025 {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        l1 = reverseList(l1);
        l2 = reverseList(l2);
        ListNode pre = new ListNode();
        ListNode head = pre;
        int bit = 0;
        while (l1 != null || l2 != null) {
            int val = (l1 == null ? 0: l1.val) + (l2 == null ? 0 : l2.val) + bit;
            if (val >= 10) {
                val -= 10;
                bit = 1;
            } else {
                bit = 0;
            }
            ListNode node = new ListNode(val);
            pre.next = node;
            pre = node;
            if (l1 != null) {
                l1 = l1.next;
            }
            if (l2 != null) {
                l2 = l2.next;
            }
        }

        if (bit == 1) {
            ListNode node = new ListNode(1);
            pre.next = node;
        }
        return reverseList(head.next);
    }

    public ListNode reverseList(ListNode node) {
        ListNode pre = null;
        ListNode next = null;
        while (node != null) {
            next = node.next;
            node.next = pre;
            pre = node;
            node = next;
        }
        return pre;
    }

    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; }
    }
}

​
/** 225. 用队列实现栈
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:
void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。*/

class MyStack {

    public Queue<Integer> queue1;
    public Queue<Integer> queue2;
    public int size;
    public boolean which;

    public MyStack() {
        queue1 = new LinkedList<>();
        queue2 = new LinkedList<>();
        size = 0;
        which = true;
    }

    public void push(int x) {
        if (which) {
            queue1.offer(x);
        } else {
            queue2.offer(x);
        }
        size++;
    }

    public int pop() {
        if (which) {
            while (queue1.size() > 1) {
                queue2.offer(queue1.poll());
            }
            size--;
            which = false;
            return queue1.poll();
        }

        while (queue2.size() > 1) {
            queue1.offer(queue2.poll());
        }
        size--;
        which = true;
        return queue2.poll();
    }

    public int top() {
        if (which) {
            while (queue1.size() > 1) {
                queue2.offer(queue1.poll());
            }
            return queue1.peek();
        }

        while (queue2.size() > 1) {
            queue1.offer(queue2.poll());
        }
        return queue2.peek();
    }

    public boolean empty() {
        return size == 0;
    }
}
/** 198. 打家劫舍
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
示例 1:
输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4 。
示例 2:
输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
     偷窃到的最高金额 = 2 + 9 + 1 = 12 。
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 400*/

class Solution {
    // public int rob(int[] nums) {
    //     return process(nums, 0);
    // }

    // public int process(int[] nums, int i) {
    //     if (i >= nums.length) {
    //         return 0;
    //     }
    //     if (i == nums.length - 1) {
    //         return nums[i];
    //     }
    //     return Math.max(process(nums, i + 1), nums[i] + process(nums, i + 2));
    // }

    public int rob(int[] nums) {
        if (nums.length == 1) {
            return nums[0];
        }
        int[] dp = new int[nums.length];
        dp[nums.length - 1] = nums[nums.length - 1];
        dp[nums.length - 2] = Math.max(nums[nums.length - 1], nums[nums.length - 2]);
        for (int i = nums.length - 3; i >= 0; i--) {
            dp[i] = Math.max(dp[i + 1], dp[i + 2] + nums[i]);
        }
        return dp[0];
    }
}
/**
 * 120. 三角形最小路径和
 * 给定一个三角形 triangle ,找出自顶向下的最小路径和。
 * 每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。也就是说,如果正位于当前行的下标 i ,那么下一步可以移动到下一行的下标 i 或 i + 1 。
 * 示例 1:
 * 输入:triangle = [[2],[3,4],[6,5,7],[4,1,8,3]]
 * 输出:11
 * 解释:如下面简图所示:
 *    2
 *   3 4
 *  6 5 7
 * 4 1 8 3
 * 自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
 * 示例 2:
 * 输入:triangle = [[-10]]
 * 输出:-10
 */

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Code120 {
    public static int minimumTotal(List<List<Integer>> triangle) {
        return process(triangle, 0, 0);
    }

    public static int process(List<List<Integer>> triangle, int i, int pos) {
        if (i == triangle.size() - 1) {
            return triangle.get(i).get(pos);
        }

        return triangle.get(i).get(pos) + Math.min(process(triangle, i + 1, pos), process(triangle, i + 1, pos + 1));
    }

    public static void main(String[] args) {
        List<List<Integer>> triangle = new ArrayList<List<Integer>>() {{
            add(Arrays.asList(2));
            add(Arrays.asList(3, 4));
            add(Arrays.asList(6, 5, 7));
            add(Arrays.asList(4, 1, 8, 3));
        }};
        System.out.println(minimumTotal(triangle));
    }

    public static int minimumTotal2(List<List<Integer>> triangle) {
        int[][] dp = new int[triangle.size()][triangle.size()];
        for (int i = 0; i <= triangle.size() - 1; i++) {
            dp[triangle.size() - 1][i] = triangle.get(triangle.size() - 1).get(i);
        }
        for (int i = triangle.size() - 2; i >= 0; i--) {
            for (int j = 0; j <= i; j++) {
                dp[i][j] = triangle.get(i).get(j) + Math.min(dp[i + 1][j], dp[i + 1][j + 1]);
            }
        }
        return dp[0][0];
    }
}
/**
 * 86. 分隔链表
 * 给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。
 * 你应当 保留 两个分区中每个节点的初始相对位置。
 * 示例 1:
 * 输入:head = [1,4,3,2,5,2], x = 3
 * 输出:[1,2,2,4,3,5]
 * 示例 2:
 * 输入:head = [2,1], x = 2
 * 输出:[1,2]
 * 提示:
 * 链表中节点的数目在范围 [0, 200] 内
 * -100 <= Node.val <= 100
 * -200 <= x <= 200
 */

public class Code86 {
    public static ListNode partition(ListNode head, int x) {
        ListNode smallNode = new ListNode(0);
        ListNode smallHead = smallNode;
        ListNode bigNode = new ListNode(0);
        ListNode bigHead = bigNode;
        while (head != null) {
            if (head.val < x) {
                smallNode.next = head;
                smallNode = head;
            } else {
                bigNode.next = head;
                bigNode = head;
            }
            head = head.next;
        }
        if (bigHead.next != null) {
            smallNode.next = bigHead.next;
        }
        bigNode.next = null;
        return smallHead.next;

    }

    public static class ListNode {
      int val;
      ListNode next;
      ListNode() {}
      ListNode(int val) { this.val = val; }
      ListNode(int val, ListNode next) { this.val = val; this.next = next; }
    }

    public static void main(String[] args) {
        ListNode head = new ListNode(2);
        ListNode node2 = new ListNode(1);
        head.next = node2;
        ListNode node = partition(head, 2);
        while (node != null) {
            System.out.println(node.val);
            node = node.next;
        }
    }
}

尝试

失败原因:超出时间限制

/**
 * 给你一个长度为 n 的二维整数数组 items 和一个整数 k 。
 * items[i] = [profiti, categoryi],其中 profiti 和 categoryi 分别表示第 i 个项目的利润和类别。
 * 现定义 items 的 子序列 的 优雅度 可以用 total_profit + distinct_categories2 计算,其中 total_profit 是子序列中所有项目的利润总和,
 * distinct_categories 是所选子序列所含的所有类别中不同类别的数量。
 * 你的任务是从 items 所有长度为 k 的子序列中,找出 最大优雅度 。
 * 用整数形式表示并返回 items 中所有长度恰好为 k 的子序列的最大优雅度。
 * 注意:数组的子序列是经由原数组删除一些元素(可能不删除)而产生的新数组,且删除不改变其余元素相对顺序。
 * @since 2024/6/13
 */

import java.util.*;

public class Code2813 {

    static long maxElegance = Long.MIN_VALUE;

    public static long findMaximumElegance(int[][] items, int k) {
        List<Integer> findedKindList = new ArrayList<>();
        List<Integer> findedElementList = new ArrayList<>();
        findElements(items, findedElementList, k, findedKindList);
        return maxElegance;
    }

    /**
     *
     * @param findedElementList 已选择序列的index
     * @param k 剩余子序列数量
     * @param findedKindList 已选择序列的category
     */
    public static void findElements(int[][] items, List<Integer> findedElementList, int k, List<Integer> findedKindList) {
        if (k <= 0) {
            long elegance = calElegance(items, findedElementList, findedKindList);
            maxElegance = Math.max(elegance, maxElegance);
            return;
        }

        Set<Integer> elements = findMaxElement(items, findedElementList, findedKindList);
//        System.out.println(elements);
        if (elements.isEmpty()) {
            return;
        }

        k--;
        for (int element : elements) {
            findedElementList.add(element);
            findedKindList.add(items[element][1]);
            findElements(items, findedElementList, k, findedKindList);
            findedElementList.remove(findedElementList.size() - 1);
            findedKindList.remove(findedKindList.size() - 1);
        }

    }

    public static Set<Integer> findMaxElement(int[][] items, List<Integer> findedElementList, List<Integer> findedKindList) {
        int max = Integer.MIN_VALUE;
        Set<Integer> elements = new HashSet<>();
        int find = -1;

        // 找出最大profiti
        for (int i = 0; i <= items.length -1; i++) {
            if (items[i][0] > max && !findedElementList.contains(i)) {
                max = items[i][0];
                find = i;
            }
        }

        if (find == -1) {
            return elements;
        }

        elements.add(find);
        if (!findedKindList.contains(items[find][1])) {
            return elements;
        }

        // 找出category不同的最大profiti
        max = Integer.MIN_VALUE;
        find = -1;
        for (int i = 0; i <= items.length - 1; i++) {
            if (items[i][0] > max && !findedElementList.contains(i) && !findedKindList.contains(items[i][1])) {
                max = items[i][0];
                find = i;
            }
        }
        if (find == -1) {
            return elements;
        }

        elements.add(find);
        return elements;
    }

    public static long calElegance(int[][] items, List<Integer> findedElementList, List<Integer> findedKindList) {
        long elegance1 = 0L;
        for (int element : findedElementList) {
            elegance1 += items[element][0];
        }
        Set<Integer> findedKindSet = new HashSet<>(findedKindList);
        return elegance1 + (long) findedKindSet.size() * findedKindSet.size();
    }

    public static void main(String[] args) {
        int[][] items = new int[3][2];
        items[0][0] = 1;
        items[0][1] = 3;
        items[1][0] = 1;
        items[1][1] = 1;
        items[2][0] = 4;
        items[2][1] = 3;
        System.out.println(findMaximumElegance(items, 2));
    }
}
/** 205. 同构字符串
给定两个字符串 s 和 t ,判断它们是否是同构的。
如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。
每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。*/

class Solution {
    public boolean isIsomorphic(String s, String t) {
        if (s == null || t == null|| s.length() != t.length()) {
            return false;
        }

        Map<Character, Character> map = new HashMap<>();
        char[] c1 = s.toCharArray();
        char[] c2 = t.toCharArray();
        for (int i = 0; i <= c1.length - 1; i++) {
            if (map.containsKey(c1[i]) && map.get(c1[i]) != c2[i]) {
                return false;
            }
            map.put(c1[i], c2[i]);
        }
        Set<Character> set = new HashSet<>();
        for (Character c : map.values()) {
            if (!set.add(c)) {
                return false;
            }
        }
        return true;
    }
}

其他来源

/**
 * 给定一个非空字符串S,其被N个‘-’分隔成N+1的子串,给定正整数K,要求除第一个子串外,其余的子串每K个字符组成新的子串,并用‘-’分隔。对于新组成的每一个子串,如果它含有的小写字母比大写字母多,则将这个子串的所有大写字母转换为小写字母;反之,如果它含有的大写字母比小写字母多,则将这个子串的所有小写字母转换为大写字母;大小写字母的数量相等时,不做转换。
 * 输入描述:
 * 输入为两行,第一行为参数K,第二行为字符串S。
 * 输出描述:
 * 输出转换后的字符串。
 * 示例1
 * 输入
 * 3
 * 12abc-abCABc-4aB@
 * 输出
 * 12abc-abc-ABC-4aB-@
 * 说明
 * 子串为12abc、abCABc、4aB@,第一个子串保留,后面的子串每3个字符一组为abC、ABc、4aB、@,abC中小写字母较多,转换为abc,ABc中大写字母较多,转换为ABC,4aB中大小写字母都为1个,不做转换,@中没有字母,连起来即12abc-abc-ABC-4aB-@
 * 示例2
 * 输入
 * 12
 * 12abc-abCABc-4aB@
 * 输出
 * 12abc-abCABc4aB@
 * 说明
 * 子串为12abc、abCABc、4aB@,第一个子串保留,后面的子串每12个字符一组为abCABc4aB@,这个子串中大小写字母都为4个,不做转换,连起来即12abc-abCABc4aB@
 * 作者:yaozi
 * 链接:https://leetcode.cn/circle/discuss/niKSMZ/
 * 来源:力扣(LeetCode)
 * 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 */

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Code1 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int k = sc.nextInt();
        String str = sc.next();
        String[] substrings = str.split("-");
        List<String> strs = new ArrayList<>();
        strs.add(substrings[0]);
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i <= substrings.length - 1; i++) {
            sb.append(substrings[i]);
        }
        int i = 0;
        for (; i <= sb.length() - k - 1; i += k) {
            strs.add(transferStr(sb.substring(i, i + k)));
        }
        strs.add(transferStr(sb.substring(i, sb.length())));
        System.out.println(String.join("-", strs));
    }

    public static String transferStr(String str) {
        int upper = 0;
        int lower = 0;
        for (int i = 0; i <= str.length() - 1; i++) {
            char c = str.charAt(i);
            if (c >= 'A' && c <= 'Z') {
                upper++;
            } else if (c >= 'a' && c <= 'z') {
                lower++;
            }
        }
        if (upper > lower) {
            return str.toUpperCase();
        } else if (upper < lower) {
            return str.toLowerCase();
        }
        return str;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值