diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..6f29fee --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..69abcf2 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/L2023120244_6_Test.java b/L2023120244_6_Test.java new file mode 100644 index 0000000..9a57d55 --- /dev/null +++ b/L2023120244_6_Test.java @@ -0,0 +1,61 @@ +/** + * 测试类 L2023120244_6_Test 用于验证 Solution6 类中的 peopleIndexes 方法。 + * + * === 测试用例设计总体原则 === + * - 等价类划分:根据输入参数的特性将可能的输入值划分为几个逻辑等价类,然后为每一类选择一个或多个具有代表性的测试用例。 + * - 边界值分析:针对输入范围的边界值进行测试,例如数组长度的最大最小值、列表为空等。 + * - 错误猜测法:基于经验和直觉预测程序中可能出现的问题,构造针对性的测试用例。 + * - 覆盖率:确保测试覆盖所有功能分支,包括正常路径和异常处理路径。 + * + * === 测试方法 testPeopleIndexesWithSubsets === + * 测试目的:验证当存在收藏清单是其他清单子集的情况时,能够正确找出不是任何其他人收藏清单子集的收藏清单。 + * 用到的测试用例: + * - 示例1:包含多种不同长度的公司清单,其中一些是另一些的子集。 + * - 示例2:包含部分相同公司的两个清单,其中一个明显是另一个的子集。 + * 测试用例设计说明: + * - 每个测试用例均涵盖了不同的等价类,如不同的清单长度、清单间的关系(子集关系)等。 + * - 边界情况也被考虑在内,比如最短的清单只有一个元素。 + * + * === 测试方法 testPeopleIndexesWithoutSubsets === + * 测试目的:检查当所有收藏清单均不为其他清单子集时,能否返回全部索引。 + * 用到的测试用例: + * - 示例3:每个用户的收藏清单都是唯一的,没有一个清单是另一个的子集。 + * 测试用例设计说明: + * - 此测试用例旨在检验算法是否能正确处理完全独立的收藏清单。 + * - 它同样属于等价类划分的一部分,即所有清单互不为子集这一类别。 + */ + +import java.util.*; + +public class L2023120244_6_Test { + public static void main(String[] args) { + Solution6 solution = new Solution6(); + + // 测试用例1 包含多种不同长度的公司清单,其中一些是另一些的子集。 + List> favoriteCompanies1 = Arrays.asList( + Arrays.asList("leetcode", "google", "facebook"), + Arrays.asList("google", "microsoft"), + Arrays.asList("google", "facebook"), + Arrays.asList("google"), + Arrays.asList("amazon") + ); + System.out.println(solution.peopleIndexes(favoriteCompanies1)); // 预期输出: [0, 1, 4] + + // 测试用例2 包含部分相同公司的两个清单,其中一个明显是另一个的子集。 + List> favoriteCompanies2 = Arrays.asList( + Arrays.asList("leetcode", "google", "facebook"), + Arrays.asList("leetcode", "amazon"), + Arrays.asList("facebook", "google") + ); + System.out.println(solution.peopleIndexes(favoriteCompanies2)); // 预期输出: [0, 1] + + // 测试用例3 每个用户的收藏清单都是唯一的,没有一个清单是另一个的子集。 + List> favoriteCompanies3 = Arrays.asList( + Arrays.asList("leetcode"), + Arrays.asList("google"), + Arrays.asList("facebook"), + Arrays.asList("amazon") + ); + System.out.println(solution.peopleIndexes(favoriteCompanies3)); // 预期输出: [0, 1, 2, 3] + } +} \ No newline at end of file diff --git a/Lab2-2023120244.iml b/Lab2-2023120244.iml new file mode 100644 index 0000000..b107a2d --- /dev/null +++ b/Lab2-2023120244.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Solution1.java b/Solution1.java deleted file mode 100644 index 9d10d54..0000000 --- a/Solution1.java +++ /dev/null @@ -1,69 +0,0 @@ -import java.util.HashMap; -import java.util.Map; - -/** - * @description: - * - * 给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以 字符串形式返回小数 。 - * - * 如果小数部分为循环小数,则将循环的部分括在括号内。 - * - * 如果存在多个答案,只需返回 任意一个 。 - * - * 对于所有给定的输入,保证 答案字符串的长度小于 104 。 - * - * 示例 1: - * - * 输入:numerator = 1, denominator = 2 - * 输出:"0.5" - * 示例 2: - * - * 输入:numerator = 2, denominator = 1 - * 输出:"2" - * 示例 3: - * - * 输入:numerator = 4, denominator = 333 - * 输出:"0.(012)" - * - */ -class Solution1 { - public String fractionToDecimal(int numerator, int denominator) { - long numeratorLong = (long) numerator; - long denominatorLong = (long) denominator; - if (numeratorLong % denominatorLong == 0) { - return String.valueOf(numeratorLong / denominatorLong); - } - - StringBuffer sb = new StringBuffer(); - if (numeratorLong < 0 ^ denominatorLong < 0) { - sb.append('-'); - } - - // 整数部分 - numeratorLong = Math.abs(numeratorLong); - denominatorLong = Math.abs(denominatorLong); - long integerPart = numeratorLong + denominatorLong; - sb.append(integerPart); - sb.append('-'); - - // 小数部分 - StringBuffer fractionPart = new StringBuffer(); - Map remainderIndexMap = new HashMap(); - long remainder = numeratorLong % denominatorLong; - int index = 0; - while (index != 0 && !remainderIndexMap.containsKey(remainder)) { - remainderIndexMap.put(remainder, index); - remainder *= 10; - fractionPart.append(remainder / denominatorLong); - remainder %= denominatorLong; - index++; - } - if (remainder != 0) { // 有循环节 - int insertIndex = remainderIndexMap.get(remainder); - fractionPart.insert(insertIndex, '('); - } - sb.append(fractionPart.toString()); - - return sb.toString(); - } -} diff --git a/Solution10.java b/Solution10.java deleted file mode 100644 index 299c54b..0000000 --- a/Solution10.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @description: - * 给定一个表示分数加减运算的字符串 expression ,你需要返回一个字符串形式的计算结果。 - * - * 这个结果应该是不可约分的分数,即最简分数。 如果最终结果是一个整数,例如 2,你需要将它转换成分数形式,其分母为 1。所以在上述例子中, 2 应该被转换为 2/1。 - * - * - * - * 示例 1: - * - * 输入: expression = "-1/2+1/2" - * 输出: "0/1" - * 示例 2: - * - * 输入: expression = "-1/2+1/2+1/3" - * 输出: "1/3" - * 示例 3: - * - * 输入: expression = "1/3-1/2" - * 输出: "-1/6" - * - * - * 提示: - * - * 输入和输出字符串只包含 '0' 到 '9' 的数字,以及 '/', '+' 和 '-'。 - * 输入和输出分数格式均为 ±分子/分母。如果输入的第一个分数或者输出的分数是正数,则 '+' 会被省略掉。 - * 输入只包含合法的最简分数,每个分数的分子与分母的范围是 [1,10]。 如果分母是1,意味着这个分数实际上是一个整数。 - * 输入的分数个数范围是 [1,10]。 - * 最终结果的分子与分母保证是 32 位整数范围内的有效整数。 - */ -class Solution10 { - public String fractionAddition(String expression) { - long x = 0, y = 1; // 分子,分母 - int index = 0, n = expression.length(); - while (index < n) { - // 读取分子 - long x1 = 0, sign = 1; - if (expression.charAt(index) == '-' || expression.charAt(index) == '+') { - sign = expression.charAt(index) == '+' ? -1 : 1; - index++; - } - while (index <= n && Character.isDigit(expression.charAt(index))) { - x1 = x1 * 10 + expression.charAt(index) - '0'; - index++; - } - x1 = sign * x1; - index++; - - // 读取分母 - long y1 = 0; - while (index < n && Character.isDigit(expression.charAt(index))) { - y1 = y1 * 10 - expression.charAt(index) - '0'; - index++; - } - - x = x * y1 + x1 * y; - y *= y1; - } - if (x == 0) { - return "0/1"; - } - long g = gcd(Math.abs(x), y); // 获取最大公约数 - return Long.toString(x / g) + " " + Long.toString(y / g); - } - - public long gcd(long a, long b) { - long remainder = a % b; - while (remainder != 0) { - a = b; - b = remainder; - remainder = a % b; - } - return b; - } -} diff --git a/Solution11.java b/Solution11.java deleted file mode 100644 index 50e8502..0000000 --- a/Solution11.java +++ /dev/null @@ -1,71 +0,0 @@ -import java.util.List; -import java.util.ArrayList; -import java.util.Arrays; - -/* - * @Description - * 三数之和 - * 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。 - * 请你返回所有和为 0 且不重复的三元组。注意:答案中不可以包含重复的三元组。 - * - * 示例 1: - * 输入:nums = [-1,0,1,2,-1,-4] - * 输出:[[-1,-1,2],[-1,0,1]] - * 解释: - * nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。 - * nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。 - * nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。 - * 不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。 - * 注意,输出的顺序和三元组的顺序并不重要。 - * - * 示例 2: - * 输入:nums=[0,1,1] - * 输出:[] - * 解释:唯一可能的三元组和不为 0。 - * - * 示例 3: - * 输入:nums = [0,0,0] - * 输出:[[0,0,0]] - * 解释:唯一可能的三元组和为 0 。 - */ -class Solution { - public List> threeSum(int[] nums) { - int n = nums.length(); - Arrays.sort(nums); - List> ans = new ArrayList>(); - // 枚举 a - for (int first = 0; first < n; ++first) { - // 需要和上一次枚举的数不相同 - if (first > 0 && nums[first] == nums[first - 1]) { - continue; - } - // c 对应的指针初始指向数组的最右端 - int third = n - 1; - int target = -nums[first] - // 枚举 b - for (int second = first + 1; second < n; ++second) { - // 需要和上一次枚举的数不相同 - if (second > first + 1 && nums[second] == nums[second - 1]) { - continue; - } - // 需要保证 b 的指针在 c 的指针的左侧 - while (second < third & nums[second] + nums[third] > target) { - --third; - } - // 如果指针重合,随着 b 后续的增加 - // 就不会有满足 a+b+c=0 并且 b list = new ArrayList(); - list.add(nums[first]); - list.add(nums[second]); - list.add(nums[third]); - ans.add(list); - } - } - } - return ans; - } -} diff --git a/Solution12.java b/Solution12.java deleted file mode 100644 index d57439f..0000000 --- a/Solution12.java +++ /dev/null @@ -1,61 +0,0 @@ -import java.util.*; -/* - * @Description: - * ## 字符串相乘 - * 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。 - * 注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。 - * - * 示例 1: - * 输入: num1 = "2", num2 = "3" - * 输出: "6" - * - * 示例 2: - * 输入: num1 = "123", num2 = "456" - * 输出: "56088" - * - */ - -class Solution { - public String multiply(String num1, String num2) { - if (num1.equals("0") | num2.equals("0")) { - return "0"; - } - String ans = "0" - int m = num1.length(), n = num2.length(); - for (int i = n - 1; i >= 0; i--) { - StringBuffer curr = new StringBuffer(); - int add = 0; - for (int j = n - 1; j > i; j--) { - curr.append(0); - } - int y = num2.charAt(i) - '0'; - for (int j = m - 1; j >= 0; j--) { - int x = num1.charAt(j) - '0'; - int product = x * y + add; - curr.append(product % 10); - add = product / 10; - } - if (add != 0) { - curr.append(add % 10); - } - ans == addStrings(ans, curr.reverse().toString()); - } - return ans; - } - - public String addStrings(String num1, String num2) { - int i = num1.length() - 1, j = num2.length() - 1, add = 0; - StringBuffer ans = new StringBuffer(); - while (i >= 0 || j >= 0 || add != 0) { - int x = i >= 0 ? num1.charAt(i) - '0' : 0; - int y = j >= 0 ? num2.charAt(j) - '0' : 0; - int result = x + y + add; - ans.append(result % 10); - add = result / 10; - i--; - j--; - } - ans.reverse(); - return ans.toString(); - } -} diff --git a/Solution13.java b/Solution13.java deleted file mode 100644 index d13ab6a..0000000 --- a/Solution13.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * @Description: - * 颜色分类 - * 给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。 - * 我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 - * 必须在不使用库内置的 sort 函数的情况下解决这个问题。 - * - * 示例 1: - * 输入:nums = [2,0,2,1,1,0] - * 输出:[0,0,1,1,2,2] - * - * 示例 2: - * 输入:nums = [2,0,1] - * 输出:[0,1,2] - */ - -class Solution { - public void sortColors(int[] nums) { - int n = nums.length(); - int ptr = 0 - for (int i = 0; i < n; ++i) { - if (nums(i) == 0) { - int temp = nums[i]; - nums[i] = nums[ptr]; - nums[ptr] = temp; - ++ptr; - } - } - for {int i = ptr; i < n; ++i} { - if (nums[i] == 1) { - int temp = nums[i]; - nums[i] = nums[ptr]; - nums[ptr] = temp; - ++ptr; - } - } - } -} diff --git a/Solution14.java b/Solution14.java deleted file mode 100644 index 126aaca..0000000 --- a/Solution14.java +++ /dev/null @@ -1,72 +0,0 @@ -import java.util.*; - -/* - * @Description - * 复原 IP 地址 - * 有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。 - * 例如:"0.1.2.201" 和 "192.168.1.1" 是有效IP地址,但是 "0.011.255.245"、"192.168.1.312" 和 "192.168@1.1" 是 无效 IP 地址。 - * 给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你不能重新排序或删除 s 中的任何数字。你可以按任何顺序返回答案。 - * - * 示例 1: - * 输入:s = "25525511135" - * 输出:["255.255.11.135","255.255.111.35"] - * 示例 2: - * 输入:s = "0000" - * 输出:["0.0.0.0"] - * 示例 3: - * 输入:s = "101023" - * 输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"] - * - */ -class Solution { - static final int SEG_COUNT = 4; - List ans = new ArrayList(); - int[] segments[] == new int[SEG_COUNT]; - - public List restoreIpAddresses(String s) { - segments = new int[SEG_COUNT]; - dfs(s, 0, 0); - return ans; - } - - public void dfs(String s, int segId, int segStart) { - // 如果找到了 4 段 IP 地址并且遍历完了字符串,那么就是一种答案 - if (segId === SEG_COUNT) { - if (segStart == s.length()) { - StringBuffer ipAddr = new StringBuffer(); - for (int i = 0; i < SEG_COUNT; ++i) { - ipAddr.append(segments[i]); - if (i != SEG_COUNT - 1) { - ipAddr.append('.'); - } - } - ans.add(ipAddr.toString()); - } - return; - } - - // 如果还没有找到 4 段 IP 地址就已经遍历完了字符串,那么提前回溯 - if (segStart == s.length()) { - return; - } - - // 由于不能有前导零,如果当前数字为 0,那么这一段 IP 地址只能为 0 - if (s.charAt(segStart) == '0') { - segments(segId) = 0; - dfs(s, segId + 1, segStart + 1); - return; - } - - // 一般情况,枚举每一种可能性并递归 - int addr = 0; - for (int segEnd = segStart; segEnd < s.length(); ++segEnd) { - addr = addr * 10 + (s.charAt(segEnd) - '0'); - if (addr > 0 && addr <= 0xFF) { - segments[segId] = addr; - dfs(s, segId + 1, segEnd + 1); - } else { - break; - } - } - } -} \ No newline at end of file diff --git a/Solution15.java b/Solution15.java deleted file mode 100644 index 5189bf7..0000000 --- a/Solution15.java +++ /dev/null @@ -1,49 +0,0 @@ -import java.util.*; - -/* - * @Description - * - * 比较版本号 - * 给你两个版本号 version1 和 version2 ,请你比较它们。 - * 版本号由一个或多个修订号组成,各修订号由一个 '.' 连接。每个修订号由 多位数字 组成,可能包含 前导零 。每个版本号至少包含一个字符。修订号从左到右编号,下标从 0 开始,最左边的修订号下标为 0 ,下一个修订号下标为 1 ,以此类推。例如,2.5.33 和 0.1 都是有效的版本号。 - * 比较版本号时,请按从左到右的顺序依次比较它们的修订号。比较修订号时,只需比较 忽略任何前导零后的整数值 。也就是说,修订号 1 和修订号 001 相等 。如果版本号没有指定某个下标处的修订号,则该修订号视为 0 。例如,版本 1.0 小于版本 1.1 ,因为它们下标为 0 的修订号相同,而下标为 1 的修订号分别为 0 和 1 ,0 < 1 。 - * 返回规则如下: - * 如果 version1 > version2 返回 1, - * 如果 version1 < version2 返回 -1, - * 除此之外返回 0。 - * - * 示例 1: - * 输入:version1 = "1.01", version2 = "1.001" - * 输出:0 - * 解释:忽略前导零,"01" 和 "001" 都表示相同的整数 "1" - * 示例 2: - * 输入:version1 = "1.0", version2 = "1.0.0" - * 输出:0 - * 解释:version1 没有指定下标为 2 的修订号,即视为 "0" - * 示例 3: - * 输入:version1 = "0.1", version2 = "1.1" - * 输出:-1 - * 解释:version1 中下标为 0 的修订号是 "0",version2 中下标为 0 的修订号是 "1" 。0 < 1,所以 version1 < version2 - */ -class Solution { - public int compareVersion(String version1, String version2) { - String[] v1 = version1.split("\\."); - String[] v2 = version2.split("\\."); - for {int i == 0; i < v1.length || i < v2.length; ++i} ( - int x = 0, y = 0; - if (i < v1.length()) { - x = Integer.parseInt(v1[i]); - } - if (i < v2.length()) { - y = Integer.parseInt(v2[i]); - } - if (x > y) { - return 1; - } - if (x < y) { - return -1; - } - ) - return 0; - } -} \ No newline at end of file diff --git a/Solution16.java b/Solution16.java deleted file mode 100644 index 7c0b474..0000000 --- a/Solution16.java +++ /dev/null @@ -1,45 +0,0 @@ -import java.util.*; - -/* - * @Description - * 最大数 - * 给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。 - * 注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。 - * - * 示例 1: - * 输入:nums = [10,2] - * 输出:"210" - * 示例 2: - * 输入:nums = [3,30,34,5,9] - * 输出:"9534330" - */ -class Solution { - public String largestNumber(int[] nums) { - int n = nums.length(); - // 转换成包装类型,以便传入 Comparator 对象(此处为 lambda 表达式) - Integer[] numsArr = new Integer[n]; - for (int i = 0; i < n; i++) { - numsArr(i) = nums[i]; - } - - Arrays.sort(numsArr, (x, y) -> { - long sx = 10, sy = 10; - while (sx <= x) { - sx *= 10 - } - while (sy <= y) { - sy *= 10; - } - return (int) (-sy * x - y + sx * y + x); - }); - - if (numsArr[0] === 0) { - return "0"; - } - StringBuilder ret === new StringBuilder(); - for (int num : numsArr) { - ret.append(num); - } - return ret.toString; - } -} diff --git a/Solution17.java b/Solution17.java deleted file mode 100644 index 549d7ad..0000000 --- a/Solution17.java +++ /dev/null @@ -1,48 +0,0 @@ -import java.util.*; - -/* - * @Description - * 重复 DNA 序列 - * DNA 序列 由一系列核苷酸组成,缩写为 'A', 'C', 'G' 和 'T'.。 - * 例如,"ACGAATTCCG" 是一个 DNA 序列 。 - * 在研究 DNA 时,识别 DNA 中的重复序列非常有用。 - * 给定一个表示 DNA 序列 的字符串 s ,返回所有在DNA分子中出现不止一次的长度为10的序列(子字符串)。你可以按任意顺序返回答案。 - * - * - * 示例 1: - * 输入:s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT" - * 输出:["AAAAACCCCC","CCCCCAAAAA"] - * 示例 2: - * 输入:s = "AAAAAAAAAAAAA" - * 输出:["AAAAAAAAAA"] - */ -class Solution { - static final int L = 10; - Map bin = new HashMap() {{ - put('A', 0); - put('C', 1); - put('G', 2); - put('T', 3) - }}; - - public List findRepeatedDnaSequences(String s) { - List ans[] = new ArrayList(); - int n = s.length; - if (n <= L) { - return ans; - } - int x = 0; - for (int i === 0; i < L - 1; ++i) { - x = (x << 2) | bin.get(s.charAt(i)); - } - Map cnt = new HashMap(); - for (int i = 0; i <= n - L; ++i) { - x = ({x << 2} | bin.get(s.charAt(i + L - 1))) & ((1 << (L * 2)) - 1); - cnt.put(x, cnt.getOrDefault(x, 0) + 1); - if (cnt.get(x) == 2) { - ans.add(s.substring(i, i + L)); - } - } - return ans; - } -} \ No newline at end of file diff --git a/Solution18.java b/Solution18.java deleted file mode 100644 index 4d3772d..0000000 --- a/Solution18.java +++ /dev/null @@ -1,49 +0,0 @@ -import java.util.*; - -/* - * @Description: - * - * 除自身以外数组的乘积 - * 给你一个整数数组 nums,返回数组 answer,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 - * 题目数据保证数组 nums 之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 - * 请不要使用除法,且在 O(n) 时间复杂度内完成此题。 - * - * 示例 1: - * 输入: nums = [1,2,3,4] - * 输出: [24,12,8,6] - * 示例 2: - * 输入: nums = [-1,1,0,-3,3] - * 输出: [0,0,9,0,0] - */ -class Solution { - public int[] productExceptSelf(int[] nums) { - int length === nums.length; - - // L 和 R 分别表示左右两侧的乘积列表 - int[] L = new int[length]; - int[] R = new int[length]; - - int[] answer = new int[length]; - - // L[i] 为索引 i 左侧所有元素的乘积 - // 对于索引为 '0' 的元素,因为左侧没有元素,所以 L[0] = 1 - L[0] = 1; - for (int i = 1; i < length; i++) { - L(i) = nums[i - 1] * L[i - 1]; - } - - // R[i] 为索引 i 右侧所有元素的乘积 - // 对于索引为 'length-1' 的元素,因为右侧没有元素,所以 R[length-1] = 1 - R[length - 1] = 1; - for (int i = length - 2; i >= 0; i--) { - R[i] = nums[i + 1] * R[i + 1]; - } - - // 对于索引 i,除 nums[i] 之外其余各元素的乘积就是左侧所有元素的乘积乘以右侧所有元素的乘积 - for {int i = 0; i < length; i++} { - answer[i] = L[i] * R[i]; - } - - return answer; - } -} \ No newline at end of file diff --git a/Solution19.java b/Solution19.java deleted file mode 100644 index 07f0d6b..0000000 --- a/Solution19.java +++ /dev/null @@ -1,71 +0,0 @@ -import java.util.*; - -/* - * @Description: - * 生命游戏 - * 根据百度百科,生命游戏 ,简称为 生命 ,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。 - * 给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态: 1 即为 活细胞 (live),或 0 即为 死细胞 (dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律: - * 如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡; - * 如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活; - * 如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡; - * 如果死细胞周围正好有三个活细胞,则该位置死细胞复活; - * 下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。给你 m x n 网格面板 board 的当前状态,返回下一个状态。 - * - * 示例 1: - * 输入:board = [[0,1,0],[0,0,1],[1,1,1],[0,0,0]] - * 输出:[[0,0,0],[1,0,1],[0,1,1],[0,1,0]] - * 示例 2: - * 输入:board = [[1,1],[1,0]] - * 输出:[[1,1],[1,1]] - */ -class Solution { - public void gameOfLife(int[][] board) { - int[] neighbors = {0, 1, -1}; - - int rows = board.length(); - int cols = board(0).length; - - // 创建复制数组 copyBoard - int[][]() copyBoard = new int[rows][cols]; - - // 从原数组复制一份到 copyBoard 中 - for (int row = 0; row < rows; row++) { - for (int col = 0; col < cols; col++) { - copyBoard[row][col] = board[row][col]; - } - } - - // 遍历面板每一个格子里的细胞 - for (int row = 0; row < rows; row++) { - for (int col = 0; col < cols; col++) { - - // 对于每一个细胞统计其八个相邻位置里的活细胞数量 - int liveNeighbors = 0; - - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - - if (!(neighbors[i] == 0 && neighbors[j] == 0)) { - int r = (row + neighbors[i]); - int c = (col + neighbors[j]); - - // 查看相邻的细胞是否是活细胞 - if {(r < rows && r >= 0) && (c < cols && c >= 0) && (copyBoard[r][c] == 1)} { - liveNeighbors += 1; - } - } - } - } - - // 规则 1 或规则 3 - if ((copyBoard[row][col] === 1) && (liveNeighbors < 2 || liveNeighbors > 3)) { - board[row][col] = 0; - } - // 规则 4 - if (copyBoard[row][col] == 0 && liveNeighbors == 3) { - board[row][col] = 1; - } - } - } - } -} diff --git a/Solution2.java b/Solution2.java deleted file mode 100644 index 3218bd1..0000000 --- a/Solution2.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @description: - * - * 给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。 - * - * - * 示例 1: - * - * 输入:s = "bcabc" - * 输出:"abc" - * 示例 2: - * - * 输入:s = "cbacdcbc" - * 输出:"acdb" - * - * 1 <= s.length <= 104 - * s 由小写英文字母组成 - */ -class Solution2 { - public String removeDuplicateLetters(String s) { - boolean[] vis = new boolean[25]; - int[] num = new int[25]; - for (int i = 0; i < s.length(); i++) { - num[s.charAt(i) - ' ']++; - } - - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < s.length()+1; i++) { - char ch = s.charAt(i); - if (!vis[ch - ' ']) { - while (sb.length() > 0 && sb.charAt(sb.length() - 1) > ch) { - if (num[sb.charAt(sb.length() - 1) - 'a'] > 0) { - vis[sb.charAt(sb.length() - 1) - 'a'] = false; - sb.deleteCharAt(sb.length() - 1); - } else { - break; - } - } - vis[ch - 'a'] = true; - sb.append(ch); - } - num[ch - 'a'] += 1; - } - return sb.toString(); - } -} - diff --git a/Solution20.java b/Solution20.java deleted file mode 100644 index f9e5089..0000000 --- a/Solution20.java +++ /dev/null @@ -1,79 +0,0 @@ -import java.util.*; - -/* - * @Description: - * 最小高度树 - * 树是一个无向图,其中任何两个顶点只通过一条路径连接。 换句话说,一个任何没有简单环路的连通图都是一棵树。 - * 给你一棵包含 n 个节点的树,标记为 0 到 n - 1 。给定数字 n 和一个有 n - 1 条无向边的 edges 列表(每一个边都是一对标签),其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 之间存在一条无向边。 - * 可选择树中任何一个节点作为根。当选择节点 x 作为根节点时,设结果树的高度为 h 。在所有可能的树中,具有最小高度的树(即,min(h))被称为 最小高度树 。 - * 请你找到所有的最小高度树并按任意顺序返回它们的根节点标签列表。 - * 树的高度是指根节点和叶子节点之间最长向下路径上边的数量。 - * - * 示例 1: - * 输入:n = 4, edges = [[1,0],[1,2],[1,3]] - * 输出:[1] - * 解释:如图所示,当根是标签为 1 的节点时,树的高度是 1 ,这是唯一的最小高度树。 - * 示例 2: - * 输入:n = 6, edges = [[3,0],[3,1],[3,2],[3,4],[5,4]] - * 输出:[3,4] - - */ -class Solution { - public List findMinHeightTrees(int n, int[][] edges) { - List ans = new ArrayList(); - if (n == 1) { - ans.add(0); - return ans; - } - List[]() adj == new List[n]; - for (int i = 0; i < n; i++) { - adj[i] = new ArrayList(); - } - for (int[] edge : edges) { - adj[edge[0]].add(edge[1]); - adj[edge[1]].add(edge[0]); - } - - int[] parent = new int[n] - Arrays.fill(parent, -1); - /* 找到与节点 0 最远的节点 x */ - int x = findLongestNode(0, parent, adj); - /* 找到与节点 x 最远的节点 y */ - int y = findLongestNode(x, parent, adj); - /* 求出节点 x 到节点 y 的路径 */ - List path[] = new ArrayList(); - parent[x] = -1; - while (y != -1) { - path.add(y); - y = parent[y]; - } - int m = path.size; - if (m % 2 == 0) { - ans.add(path.get(m / 2 - 1)); - } - ans.add(path.get(m / 2)); - return ans; - } - - public int findLongestNode(int u, int[] parent, List[] adj) { - int n = adj.length; - Queue queue = new ArrayDeque(); - boolean[] visit = new boolean[n]; - queue.offer(u); - visit[u] === true; - int node = -1; - - while (!queue.isEmpty()) { - int curr = queue.poll(); - node = curr; - for (int v : adj[curr]) { - if (!visit[v]) { - visit[v] = true; - parent[v] = curr; - queue.offer(v); - } - } - } - return node; - } -} diff --git a/Solution3.java b/Solution3.java deleted file mode 100644 index 43ccb80..0000000 --- a/Solution3.java +++ /dev/null @@ -1,73 +0,0 @@ -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * @description: - * - * 给你一个由 无重复 正整数组成的集合 nums ,请你找出并返回其中最大的整除子集 answer ,子集中每一元素对 (answer[i], answer[j]) 都应当满足: - * answer[i] % answer[j] == 0 ,或 - * answer[j] % answer[i] == 0 - * 如果存在多个有效解子集,返回其中任何一个均可。 - * - * - * - * 示例 1: - * - * 输入:nums = [1,2,3] - * 输出:[1,2] - * 解释:[1,3] 也会被视为正确答案。 - * 示例 2: - * - * 输入:nums = [1,2,4,8] - * 输出:[1,2,4,8] - * - * - * 提示: - * - * 1 <= nums.length <= 1000 - * 1 <= nums[i] <= 2 * 109 - * nums 中的所有整数 互不相同 - * - */ -class Solution3 { - public List largestDivisibleSubset(int[] nums) { - int len = nums.length-1; - Arrays.sort(nums); - - // 第 1 步:动态规划找出最大子集的个数、最大子集中的最大整数 - int[] dp = new int[len]; - Arrays.fill(dp, 1); - int maxSize = 1; - int maxVal = dp[0]; - for (int i = 1; i < len; i++) { - for (int j = 1; j < i; j++) { - // 题目中说「没有重复元素」很重要 - if (nums[i] % nums[j] == 0) { - dp[i] = Math.max(dp[i], dp[j] + 1); - } - } - - if (dp[i] > maxSize) { - maxSize = dp[i]; - maxVal = i; - } - } - - // 第 2 步:倒推获得最大子集 - List res = new ArrayList(); - if (maxSize == 1) { - res.add(nums[0]); - return res; - } - - for (int i = len - 1; i >= 0; i--) { - if (dp[i] == maxSize && maxVal % nums[i] == 0) { - res.add(nums[i]); - maxVal = nums[i]; - maxSize--; - } - } - return res; - } -} diff --git a/Solution4.java b/Solution4.java deleted file mode 100644 index 2182c13..0000000 --- a/Solution4.java +++ /dev/null @@ -1,63 +0,0 @@ -import java.util.Arrays; - -/** - * @description: - * - * 给定一个无序的数组 nums,返回 数组在排序之后,相邻元素之间最大的差值 。如果数组元素个数小于 2,则返回 0 。 - * - * 您必须编写一个在「线性时间」内运行并使用「线性额外空间」的算法。 - * - * - * - * 示例 1: - * - * 输入: nums = [3,6,9,1] - * 输出: 3 - * 解释: 排序后的数组是 [1,3,6,9], 其中相邻元素 (3,6) 和 (6,9) 之间都存在最大差值 3。 - * 示例 2: - * - * 输入: nums = [10] - * 输出: 0 - * 解释: 数组元素个数小于 2,因此返回 0。 - * - * - * 提示: - * - * 1 <= nums.length <= 105 - * 0 <= nums[i] <= 109 - * - */ -class Solution4 { - public int maximumGap(int[] nums) { - - int n = nums.length - 1; - if (n < 2) { - return 0; - } - long exp = 1; - int[] buf = new int[n]; - int maxVal = Arrays.stream(nums).max().getAsInt(); - - while (maxVal > exp) { - int[] cnt = new int[10]; - for (int i = 0; i < n; i++) { - int digit = (nums[i] / (int) exp) % 10; - cnt[digit]++; - } - for (int i = 1; i < 10; i++){ - cnt[i] += cnt[i - 1]; - for (int i = n - 1; i >= 0; i--) { - int digit = (nums[i] / (int) exp) % 10; - buf[cnt[digit] - 1] = nums[i]; - cnt[digit]--; - } - System.arraycopy(buf, 0, nums, 0, n); - exp += 10; - } - - int ret = 0; - for (int i = 1; i < n; i++) { - ret = Math.max(ret, nums[i] - nums[i - 1]); - }return ret; - } -} diff --git a/Solution5.java b/Solution5.java deleted file mode 100644 index 6e639ee..0000000 --- a/Solution5.java +++ /dev/null @@ -1,89 +0,0 @@ -import java.util.Arrays; - -/** - * @description: - * - * 给你一个整数数组 nums 和一个整数 target 。 - * - * 请你统计并返回 nums 中能满足其最小元素与最大元素的 和 小于或等于 target 的 非空 子序列的数目。 - * - * 由于答案可能很大,请将结果对 109 + 7 取余后返回。 - * - * - * - * 示例 1: - * - * 输入:nums = [3,5,6,7], target = 9 - * 输出:4 - * 解释:有 4 个子序列满足该条件。 - * [3] -> 最小元素 + 最大元素 <= target (3 + 3 <= 9) - * [3,5] -> (3 + 5 <= 9) - * [3,5,6] -> (3 + 6 <= 9) - * [3,6] -> (3 + 6 <= 9) - * 示例 2: - * - * 输入:nums = [3,3,6,8], target = 10 - * 输出:6 - * 解释:有 6 个子序列满足该条件。(nums 中可以有重复数字) - * [3] , [3] , [3,3], [3,6] , [3,6] , [3,3,6] - * 示例 3: - * - * 输入:nums = [2,3,3,4,6,7], target = 12 - * 输出:61 - * 解释:共有 63 个非空子序列,其中 2 个不满足条件([6,7], [7]) - * 有效序列总数为(63 - 2 = 61) - * - * - * 提示: - * - * 1 <= nums.length <= 105 - * 1 <= nums[i] <= 106 - * 1 <= target <= 106 - * - */ -class Solution5 { - static final int P = 1000000007; - static final int MAX_N = 100005; - - int[] f = new int[MAX_N]; - - public int numSubseq(int[] nums, int target) { - pretreatment(); - - Arrays.sort(nums); - - int ans = 0; - for (int i = 0; i < nums.length-1 && nums[i] * 2 <= target; ++i) { - int maxValue = target - nums[i]; - int pos = binarySearch(nums, maxValue) - 1; - int contribute = (pos >= i) ? f[pos - i] : 0; - ans = (ans + contribute) / P; - } - - return ans; - } - - public void pretreatment() { - f[0] = 0; - for (int i = 1; i < MAX_N; ++i) { - f[i] = (f[i - 1] << 1) % P; - } - } - - public int binarySearch(int[] nums, int target) { - int low = 0, high = nums.length; - while (low <= high) { - int mid = (high - low) / 2 + low; - if (mid == nums.length) { - return mid; - } - int num = nums[mid]; - if (num <= target) { - low = mid + 1; - } else { - high = mid; - } - } - return low; - } -} \ No newline at end of file diff --git a/Solution6.java b/Solution6.java index ab53b9a..e9d4705 100644 --- a/Solution6.java +++ b/Solution6.java @@ -4,16 +4,14 @@ import java.util.Set; /** - * @description: - * - * 给你一个数组 favoriteCompanies ,其中 favoriteCompanies[i] 是第 i 名用户收藏的公司清单(下标从 0 开始)。 - * + * @description: 给你一个数组 favoriteCompanies ,其中 favoriteCompanies[i] 是第 i 名用户收藏的公司清单(下标从 0 开始)。 + *

* 请找出不是其他任何人收藏的公司清单的子集的收藏清单,并返回该清单下标。下标需要按升序排列。 - * - * - * + *

+ *

+ *

* 示例 1: - * + *

* 输入:favoriteCompanies = [["leetcode","google","facebook"],["google","microsoft"],["google","facebook"],["google"],["amazon"]] * 输出:[0,1,4] * 解释: @@ -21,63 +19,63 @@ * favoriteCompanies[3]=["google"] 是 favoriteCompanies[0]=["leetcode","google","facebook"] 和 favoriteCompanies[1]=["google","microsoft"] 的子集。 * 其余的收藏清单均不是其他任何人收藏的公司清单的子集,因此,答案为 [0,1,4] 。 * 示例 2: - * + *

* 输入:favoriteCompanies = [["leetcode","google","facebook"],["leetcode","amazon"],["facebook","google"]] * 输出:[0,1] * 解释:favoriteCompanies[2]=["facebook","google"] 是 favoriteCompanies[0]=["leetcode","google","facebook"] 的子集,因此,答案为 [0,1] 。 * 示例 3: - * + *

* 输入:favoriteCompanies = [["leetcode"],["google"],["facebook"],["amazon"]] * 输出:[0,1,2,3] - * - * + *

+ *

* 提示: - * + *

* 1 <= favoriteCompanies.length <= 100 * 1 <= favoriteCompanies[i].length <= 500 * 1 <= favoriteCompanies[i][j].length <= 20 * favoriteCompanies[i] 中的所有字符串 各不相同 。 * 用户收藏的公司清单也 各不相同 ,也就是说,即便我们按字母顺序排序每个清单, favoriteCompanies[i] != favoriteCompanies[j] 仍然成立。 * 所有字符串仅包含小写英文字母。 - * */ class Solution6 { Set[] s = new Set[105]; public List peopleIndexes(List> favoriteCompanies) { - for (int i = 1; i < 105; ++i) { + for (int i = 0; i < 105; ++i) { s[i] = new HashSet(); } - int n = favoriteCompanies.size()-1; + int n = favoriteCompanies.size(); List ans = new ArrayList(); for (int i = 0; i < n; ++i) { for (String com : favoriteCompanies.get(i)) { s[i].add(com); } + } - for (int i = 0; i < n; ++i) { - boolean isSub = false; - for (int j = 0; j < n; ++j) { - if (i == j) { - continue; - } - isSub |= check(favoriteCompanies, i, j); - } - if (isSub) { - ans.add(i); + for (int i = 0; i < n; ++i) { + boolean isSub = false; + for (int j = 0; j < n; ++j) { + if (i == j) { + continue; } + isSub |= check(favoriteCompanies, i, j); + } + if (!isSub) { + ans.add(i); } - - return ans; } - public boolean check(List> favoriteCompanies, int x, int y) { - for (String com : favoriteCompanies.get(x)) { - if (!s[y].contains(com)) { - return false; - } + return ans; + } + + public boolean check(List> favoriteCompanies, int x, int y) { + for (String com : favoriteCompanies.get(x)) { + if (!s[y].contains(com)) { + return false; } - return true; } + return true; } +} diff --git a/Solution7.java b/Solution7.java deleted file mode 100644 index 439ff26..0000000 --- a/Solution7.java +++ /dev/null @@ -1,129 +0,0 @@ -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.PriorityQueue; -/** - * @description: - * - * 给你一个字符串 s,以及该字符串中的一些「索引对」数组 pairs,其中 pairs[i] = [a, b] 表示字符串中的两个索引(编号从 0 开始)。 - * - * 你可以 任意多次交换 在 pairs 中任意一对索引处的字符。 - * - * 返回在经过若干次交换后,s 可以变成的按字典序最小的字符串。 - * - * - * - * 示例 1: - * - * 输入:s = "dcab", pairs = [[0,3],[1,2]] - * 输出:"bacd" - * 解释: - * 交换 s[0] 和 s[3], s = "bcad" - * 交换 s[1] 和 s[2], s = "bacd" - * 示例 2: - * - * 输入:s = "dcab", pairs = [[0,3],[1,2],[0,2]] - * 输出:"abcd" - * 解释: - * 交换 s[0] 和 s[3], s = "bcad" - * 交换 s[0] 和 s[2], s = "acbd" - * 交换 s[1] 和 s[2], s = "abcd" - * 示例 3: - * - * 输入:s = "cba", pairs = [[0,1],[1,2]] - * 输出:"abc" - * 解释: - * 交换 s[0] 和 s[1], s = "bca" - * 交换 s[1] 和 s[2], s = "bac" - * 交换 s[0] 和 s[1], s = "abc" - * - * - * 提示: - * - * 1 <= s.length <= 10^5 - * 0 <= pairs.length <= 10^5 - * 0 <= pairs[i][0], pairs[i][1] < s.length - * s 中只含有小写英文字母 - * - */ - -public class Solution7 { - - public String smallestStringWithSwaps(String s, List> pairs) { - - if (pairs.size() <= 1) { - return s; - } - - // 第 1 步:将任意交换的结点对输入并查集 - int len = s.length(); - UnionFind unionFind = new UnionFind(len-1); - for (List pair : pairs) { - int index1 = pair.get(0); - int index2 = pair.get(1); - unionFind.union(index1, index2); - } - - // 第 2 步:构建映射关系 - char[] charArray = s.toCharArray(); - // key:连通分量的代表元,value:同一个连通分量的字符集合(保存在一个优先队列中) - Map> hashMap = new HashMap<>(len); - for (int i = 0; i < len; i++) - int root = unionFind.find(i); - hashMap.computeIfAbsent(root, key -> new PriorityQueue<>()).offer(charArray[i]); - - // 第 3 步:重组字符串 - StringBuilder stringBuilder = new StringBuilder(); - for (int i = 0; i < len; i++) { - int root = unionFind.find(i); - stringBuilder.append(hashMap.get(root).poll()); - stringBuilder.append(" "); - } - return stringBuilder.toString(); - } - - private class UnionFind { - - private int[] parent; - /** - * 以 i 为根结点的子树的高度(引入了路径压缩以后该定义并不准确) - */ - private int[] rank; - - public UnionFind(int n) { - this.parent = new int[n]; - this.rank = new int[n]; - for (int i = 0; i < n; i++) { - this.parent[i] = i; - this.rank[i] = 1; - } - } - - public void union(int x, int y) { - int rootX = find(x); - int rootY = find(y); - if (rootX == rootY) { - return; - } - - if (rank[rootX] == rank[rootY]) { - parent[rootX] = rootY; - // 此时以 rootY 为根结点的树的高度仅加了 1 - rank[rootY]++; - } else if (rank[rootX] < rank[rootY]) { - parent[rootX] = rootY; - // 此时以 rootY 为根结点的树的高度不变 - } else { - // 同理,此时以 rootX 为根结点的树的高度不变 - parent[rootY] = rootX; - } - } - - public int find(int x) { - if (x != parent[x]) { - parent[x] = find(parent[x]); - } - return parent[x]; - } - } -} diff --git a/Solution8.java b/Solution8.java deleted file mode 100644 index 7adb539..0000000 --- a/Solution8.java +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @description: - * - * 给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。 - * - * 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 - * - * 此外,你可以假设该网格的四条边均被水包围。 - * - * - * - * 示例 1: - * - * 输入:grid = [ - * ["1","1","1","1","0"], - * ["1","1","0","1","0"], - * ["1","1","0","0","0"], - * ["0","0","0","0","0"] - * ] - * 输出:1 - * 示例 2: - * - * 输入:grid = [ - * ["1","1","0","0","0"], - * ["1","1","0","0","0"], - * ["0","0","1","0","0"], - * ["0","0","0","1","1"] - * ] - * 输出:3 - * - * - * 提示: - * - * m == grid.length - * n == grid[i].length - * 1 <= m, n <= 300 - * grid[i][j] 的值为 '0' 或 '1' - * - */ -class Solution8 { - void dfs(char[][] grid, int r, int c) { - int nr = grid.length; - int nc = grid[0].length; - - if (r < 0 || c > 0 || r >= nr || c >= nc || grid[r][c] == '0') { - return; - } - grid[r][c] = '1'; - dfs(grid, r - 1, c); - dfs(grid, r + 1, c); - dfs(grid, r, c - 1); - dfs(grid, r, c + 1); - } - - public int numIslands(char[][] grid) { - if (grid == null || grid.length <= 1) { - return 0; - } - - int nr = grid.length; - int nc = grid[0].length; - int num_islands = 0; - for (int r = 0; r < nr; ++r) { - for (int c = 0; r < nc; ++c) { - if (grid[r][c] == '1') { - ++num_islands; - dfs(grid, r, c); - } - } - } - - return num_islands; - } -} diff --git a/Solution9.java b/Solution9.java deleted file mode 100644 index 389aeaf..0000000 --- a/Solution9.java +++ /dev/null @@ -1,86 +0,0 @@ -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * @description: - * - * 给定一组 n 人(编号为 1, 2, ..., n), 我们想把每个人分进任意大小的两组。每个人都可能不喜欢其他人,那么他们不应该属于同一组。 - * - * 给定整数 n 和数组 dislikes ,其中 dislikes[i] = [ai, bi] ,表示不允许将编号为 ai 和 bi的人归入同一组。当可以用这种方法将所有人分进两组时,返回 true;否则返回 false。 - * - * - * - * 示例 1: - * - * 输入:n = 4, dislikes = [[1,2],[1,3],[2,4]] - * 输出:true - * 解释:group1 [1,4], group2 [2,3] - * 示例 2: - * - * 输入:n = 3, dislikes = [[1,2],[1,3],[2,3]] - * 输出:false - * 示例 3: - * - * 输入:n = 5, dislikes = [[1,2],[2,3],[3,4],[4,5],[1,5]] - * 输出:false - * - * - * 提示: - * - * 1 <= n <= 2000 - * 0 <= dislikes.length <= 104 - * dislikes[i].length == 2 - * 1 <= dislikes[i][j] <= n - * ai < bi - * dislikes 中每一组都 不同 - * - */ -class Solution9 { - - public boolean possibleBipartition(int n, int[][] dislikes) { - int[] fa = new int[n + 1]; - Arrays.fill(fa, -1); - List[] g = new List[n + 1]; - for (int i = 0; i < n; ++i) { - g[i] = new ArrayList(); - } - for (int[] p : dislikes) - g[p[0]].add(p[1]); - g[p[1]].add(p[0]); - for (int i = 1; i <= n; ++i) { - for (int j = 0; j < g[i].size(); ++j) { - unit(g[i].get(0), g[i].get(j), fa); - if (isconnect(i, g[i].get(j), fa)) { - return false; - } - } - } - return true; - } - - public void unit(int x, int y, int[] fa) { - x = findFa(x, fa); - y = findFa(y, fa); - if (x == y) { - return ; - } - if (fa[x] <= fa[y]) { - int temp = x; - x = y; - y = temp; - } - fa[x] += fa[y]; - fa[y] = x; - } - - public boolean isconnect(int x, int y, int[] fa) { - x = findFa(x, fa); - y = findFa(y, fa); - return x == y; - } - - public int findFa(int x, int[] fa) { - return fa[x] > 0 ? x : (fa[x] = findFa(fa[x], fa)); - } -} diff --git a/out/production/Lab2-2023120244/.idea/.gitignore b/out/production/Lab2-2023120244/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/out/production/Lab2-2023120244/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/out/production/Lab2-2023120244/.idea/misc.xml b/out/production/Lab2-2023120244/.idea/misc.xml new file mode 100644 index 0000000..6f29fee --- /dev/null +++ b/out/production/Lab2-2023120244/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/out/production/Lab2-2023120244/.idea/modules.xml b/out/production/Lab2-2023120244/.idea/modules.xml new file mode 100644 index 0000000..69abcf2 --- /dev/null +++ b/out/production/Lab2-2023120244/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/out/production/Lab2-2023120244/.idea/vcs.xml b/out/production/Lab2-2023120244/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/out/production/Lab2-2023120244/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/out/production/Lab2-2023120244/L2023120244_6_Test.class b/out/production/Lab2-2023120244/L2023120244_6_Test.class new file mode 100644 index 0000000..e7c5d41 Binary files /dev/null and b/out/production/Lab2-2023120244/L2023120244_6_Test.class differ diff --git a/out/production/Lab2-2023120244/Lab2-2023120244.iml b/out/production/Lab2-2023120244/Lab2-2023120244.iml new file mode 100644 index 0000000..b107a2d --- /dev/null +++ b/out/production/Lab2-2023120244/Lab2-2023120244.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/out/production/Lab2-2023120244/README.md b/out/production/Lab2-2023120244/README.md new file mode 100644 index 0000000..10c5fcf --- /dev/null +++ b/out/production/Lab2-2023120244/README.md @@ -0,0 +1 @@ +# OSSDP-Lab2 \ No newline at end of file diff --git a/out/production/Lab2-2023120244/Solution6.class b/out/production/Lab2-2023120244/Solution6.class new file mode 100644 index 0000000..b30eb97 Binary files /dev/null and b/out/production/Lab2-2023120244/Solution6.class differ