diff --git a/README.md b/README.md index 880ae49..f6fec31 100644 --- a/README.md +++ b/README.md @@ -3,21 +3,6 @@ 这是一个数据结构和算法笔记本,**书写** 并 **整理**一些常见的数据结构和其对应的相关操作。这其中**每一个类文件都是一个可以单独运行查看结果的main方法类** ,相关的关键描述和想说的话都在代码的注释中。(欢迎一同补充和完善,2019年01月04日00:07:40置为public) -1. 数组 - - [搜索二维矩阵](/src/main/java/ds/FindInDoubleArray.java) - - [数组中重复的数据](/src/main/java/ds/RepeatInArray.java) - - [合并两个有序数组](/src/main/java/ds/MergeArray.java) - - [旋转数组](/src/main/java/ds/RotateArray.java) - - [有序数组的平方](/src/main/java/ds/SortedSquares.java) - - [寻找数组的中心索引](/src/main/java/ds/PivotIndex.java) - - [两个数组的交集II](/src/main/java/ds/Intersect.java) - - [递增的三元子序列](/src/main/java/ds/IncreasingTriplet.java) - - [除自身以外数组的乘积](/src/main/java/ds/ProductExceptSelf.java) - - [存在重复元素II](/src/main/java/ds/ContainsNearbyDuplicate.java) - - [存在重复元素III](/src/main/java/ds/ContainsNearbyAlmostDuplicate.java) - - [矩阵置零](/src/main/java/ds/SetZeroes.java) - - [1486.数组异或操作](/src/main/java/ds/array/leetcode1486/Solution.java) - 4. 线性数据结构及其对应的常见算法 1. 线性表(分别基于数组和链表实现一遍) @@ -161,6 +146,10 @@ - [剑指 Offer II 015.字符串中的所有变位词](/src/main/java/ds/pointer/targetofferII015/Solution.java) - [11.盛最多水的容器](/src/main/java/ds/pointer/leetcode11/Solution.java) - [42.接雨水](/src/main/java/ds/pointer/leetcode42/Solution.java) + - [19.删除链表的倒数第N个节点](/src/main/java/ds/pointer/leetcode19/Solution.java) + - 会议调度算法 + - [252.会议室](/src/main/java/ds/pointer/leetcode252/Solution.java) + - [253.会议室II](/src/main/java/ds/pointer/leetcode253/Solution.java) 6. 滑动窗口 - [一个数组所有连续K个元素构成的子集的平均数](/src/main/java/ds/sliding/ArrayAverages.java) @@ -209,7 +198,17 @@ - [113.路径总和II](/src/main/java/ds/tree/leetcode113/Solution.java) - [257.二叉树的所有路径](/src/main/java/ds/tree/leetcode257/Solution.java) -10. 广度优先搜索(BFS) +10. 深度优先搜索(DFS) + - [129.求根节点到叶节点数字之和](/src/main/java/ds/dfs/leetcode129/Solution.java) + - 岛屿问题 + - 200 + - 1254 + - 1020 + - 695 + - 1905 + - 694 + +11. 广度优先搜索(BFS) - [111.二叉树的最小深度](/src/main/java/ds/bfs/leetcode111/Solution.java) - [102.二叉树的层序遍历](/src/main/java/ds/bfs/leetcode102/Solution.java) - [107.二叉树的层序遍历II](/src/main/java/ds/bfs/leetcode107/Solution.java) @@ -223,18 +222,31 @@ - [103.二叉树的锯齿形层次遍历](/src/main/java/ds/bfs/leetcode103/Solution.java) - [117.填充每个节点的下一个右侧节点指针II](/src/main/java/ds/bfs/leetcode117/Solution.java) -11. 数组 +12. 数组 - [59.螺旋矩阵II](/src/main/java/ds/array/leetcode59/Solution.java) - [384.打乱数组](/src/main/java/ds/array/leetcode384/Solution.java) + - [74.搜索二维矩阵](/src/main/java/ds/array/leetcode74/Solution.java) + - [442.数组中重复的数据](/src/main/java/ds/array/leetcode442/Solution.java) + - [88.合并两个有序数组](/src/main/java/ds/array/leetcode88/Solution.java) + - [189.轮转数组](/src/main/java/ds/array/leetcode189/Solution.java) + - [977.有序数组的平方](/src/main/java/ds/array/leetcode977/Solution.java) + - [724.寻找数组的中心下标](/src/main/java/ds/array/leetcode724/Solution.java) + - [350.两个数组的交集 II](/src/main/java/ds/array/leetcode350/Solution.java) + - [334.递增的三元子序列](/src/main/java/ds/array/leetcode334/Solution.java) + - [238.除自身以外数组的乘积](/src/main/java/ds/array/leetcode238/Solution.java) + - [219.存在重复元素II](/src/main/java/ds/array/leetcode219/Solution.java) + - [存在重复元素III](/src/main/java/ds/ContainsNearbyAlmostDuplicate.java) + - [矩阵置零](/src/main/java/ds/SetZeroes.java) + - [1486.数组异或操作](/src/main/java/ds/array/leetcode1486/Solution.java) -12. 链表 +13. 链表 - [203.移除链表元素](/src/main/java/ds/link/leetcode203/Solution.java) - [707.设计链表](/src/main/java/ds/link/leetcode707/MyLinkedList.java) - [剑指offer 06.从尾到头打印链表](/src/main/java/ds/link/targetoffer06/Solution.java) - [剑指offer 18.删除链表中的节点](/src/main/java/ds/link/targetoffer18/Solution.java) - [234.回文链表](/src/main/java/ds/link/leetcode234/Solution.java) -13. 哈希表 +14. 哈希表 - [242.有效的字母异位词](/src/main/java/ds/hashmap/leetcode242/Solution.java) - [349.两个数组的交集](/src/main/java/ds/hashmap/leetcode349/Solution.java) - [202.快乐数](/src/main/java/ds/hashmap/leetcode202/Solution.java) @@ -249,8 +261,9 @@ - [剑指 Offer II 011.0 和 1 个数相同的子数组](/src/main/java/ds/hashmap/targetofferII011/Solution.java) - [剑指 Offer II 012.左右两边子数组的和相等](/src/main/java/ds/hashmap/targetofferII012/Solution.java) - [剑指 Offer II 013.二维子矩阵的和](/src/main/java/ds/hashmap/targetofferII013/NumMatrix.java) + - [409.最长回文串](/src/main/java/ds/hashmap/leetcode409/Solution.java) -14. 字符串 +15. 字符串 - [Fizz Buzz](/src/main/java/ds/string/FizzBuzz.java) - [验证回文字符](/src/main/java/ds/string/ValidPalindromeString.java) - [最后一个单词的长度](/src/main/java/ds/string/LengthOfLastWord.java) @@ -260,21 +273,22 @@ - [验证回文串](/src/main/java/ds/string/PalindromeI.java) - [单词拆分](/src/main/java/ds/string/WordBreak.java) -15. 排序 +16. 排序 - [冒泡排序](/src/main/java/ds/sort/BubbleSort.java) - [插入排序](/src/main/java/ds/sort/InsertSort.java) - [选择排序](/src/main/java/ds/sort/SelectionSort.java) - [快速排序](/src/main/java/ds/sort/QuickSort.java) - [计数排序](/src/main/java/ds/sort/CountSort.java) - [堆排序](/src/main/java/ds/sort/BigHeapSort.java) + - 归并排序 -16. 贪心 +17. 贪心 - [455.分发饼干](/src/main/java/ds/greedy/leetcode455/Solution.java) - [376.摆动序列](/src/main/java/ds/greedy/leetcode376/Solution.java) - [53.最大子序和](/src/main/java/ds/greedy/leetcode53/Solution.java) - [122.买卖股票的最佳时机II](/src/main/java/ds/greedy/leetcode122/Solution.java) -17. 动态规划(DP) +18. 动态规划(DP) - 斐波拉切 - [斐波拉契数列的4种解法](/src/main/java/ds/dp/Fipolach.java) - [509.斐波那契数](/src/main/java/ds/dp/leetcode509/Solution.java) @@ -283,6 +297,7 @@ - 路径 - [60.不同路径](/src/main/java/ds/dp/leetcode60/Solution.java) - [63.不同路径II](/src/main/java/ds/dp/leetcode63/Solution.java) + - [64.最小路径和](/src/main/java/ds/dp/leetcode64/Solution.java) - [96.不同的二叉搜索树](/src/main/java/ds/dp/leetcode96/Solution.java) - [343.整数拆分](/src/main/java/ds/dp/leetcode343/Solution.java) - [三角形最小路径和](/src/main/java/ds/dp/MinimumTotal.java) @@ -294,8 +309,9 @@ - 杨辉三角 - [118.杨辉三角](/src/main/java/ds/dp/leetcode118/Solution.java) - [119.杨辉三角II](/src/main/java/ds/dp/leetcode119/Solution.java) + - [322.零钱兑换](/src/main/java/ds/dp/leetcode322/Solution.java) -18. 栈 +19. 栈 - [20.有效的括号](/src/main/java/ds/stack/leetcode20/Solution.java) - [1047.删除字符串中的所有相邻重复项](/src/main/java/ds/stack/leetcode1047/Solution.java) - [150.逆波兰表达式求值](/src/main/java/ds/stack/leetcode150/Solution.java) diff --git a/src/main/java/ds/MergeArray.java b/src/main/java/ds/MergeArray.java deleted file mode 100644 index 7e6ac02..0000000 --- a/src/main/java/ds/MergeArray.java +++ /dev/null @@ -1,29 +0,0 @@ -package ds; - -/** - * 合并两个有序数组 - *

- * 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。 - *

- * 说明: - *

- * 初始化 nums1 和 nums2 的元素数量分别为 m 和 n。 - * 你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。 - * - * @author yangyi 2019年02月09日11:10:35 - */ -public class MergeArray { - - public int[] merge(int[] nums1, int m, int[] nums2, int n) { - int p = m-- + n-- - 1; - while (m>= 0 && n>= 0) { - nums1[p--] = nums1[m]> nums2[n] ? nums1[m--] : nums2[n--]; - } - - while (n>= 0) { - nums1[p--] = nums2[n--]; - } - return nums1; - } - -} diff --git a/src/main/java/ds/PivotIndex.java b/src/main/java/ds/PivotIndex.java deleted file mode 100644 index 792dbcf..0000000 --- a/src/main/java/ds/PivotIndex.java +++ /dev/null @@ -1,70 +0,0 @@ -package ds; - -import java.util.Arrays; - -/** - * 寻找数组的中心索引 - *

- *

- * 给定一个整数类型的数组 nums,请编写一个能够返回数组"中心索引"的方法。 - *

- * 我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。 - *

- * 如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。 - *

- * 示例 1: - *

- * 输入: - * nums = [1, 7, 3, 6, 5, 6] - * 输出: 3 - * 解释: - * 索引3 (nums[3] = 6) 的左侧数之和(1 + 7 + 3 = 11),与右侧数之和(5 + 6 = 11)相等。 - * 同时, 3 也是第一个符合要求的中心索引。 - * 示例 2: - *

- * 输入: - * nums = [1, 2, 3] - * 输出: -1 - * 解释: - * 数组中不存在满足此条件的中心索引。 - * 说明: - *

- * nums 的长度范围为 [0, 10000]。 - * 任何一个 nums[i] 将会是一个范围在 [-1000, 1000]的整数。 - * - * @author yangyi 2019年02月16日23:46:58 - */ -public class PivotIndex { - - public int pivotIndex(int[] nums) { - if (nums.length < 3) { - return -1; - } - int sum = 0; - int leftSum = 0; - int rightSum = 0; - for (int i = 0; i < nums.length; i++) { - sum += nums[i]; - } - for (int i = 0; i < nums.length; i++) { - rightSum = sum - leftSum - nums[i]; - if (leftSum == rightSum) { - return i; - } - leftSum += nums[i]; - } - return -1; - } - - public static void main(String[] args) { - int[] a = {1, 7, 3, 6, 5, 6}; - int[] b = {1, 2, 3}; - int[] c = {-1, -1, 0, 1, 0, -1}; - int[] d = {-1, -1, 0, 1, 1, 0}; - PivotIndex pivotIndex = new PivotIndex(); - System.out.println(Arrays.toString(a) + "的中心索引是:" + pivotIndex.pivotIndex(a)); - System.out.println(Arrays.toString(b) + "的中心索引是:" + pivotIndex.pivotIndex(b)); - System.out.println(Arrays.toString(c) + "的中心索引是:" + pivotIndex.pivotIndex(c)); - System.out.println(Arrays.toString(d) + "的中心索引是:" + pivotIndex.pivotIndex(d)); - } -} diff --git a/src/main/java/ds/ProductExceptSelf.java b/src/main/java/ds/ProductExceptSelf.java deleted file mode 100644 index 5796f68..0000000 --- a/src/main/java/ds/ProductExceptSelf.java +++ /dev/null @@ -1,45 +0,0 @@ -package ds; - -import java.util.Arrays; - -/** - * 除自身以外数组的乘积 - *

- *

- * 给定长度为 n 的整数数组 nums,其中 n> 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。 - *

- * 示例: - *

- * 输入: [1,2,3,4] - * 输出: [24,12,8,6] - * 说明: 请不要使用除法,且在 O(n) 时间复杂度内完成此题。 - *

- * 进阶: - * 你可以在常数空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。) - * - * @author yangyi 2019年03月02日22:54:06 - */ -public class ProductExceptSelf { - - public int[] productExceptSelf(int[] nums) { - int left = 1; - int right = 1; - int len = nums.length; - int[] output = new int[len]; - for (int i = 0; i < len; i++) { - output[i] = left; - left *= nums[i]; - } - for (int j = len - 1; j>= 0; j--) { - output[j] *= right; - right *= nums[j]; - } - return output; - } - - public static void main(String[] args) { - int[] a = {1,2,3,4}; - ProductExceptSelf productExceptSelf = new ProductExceptSelf(); - System.out.println(Arrays.toString(productExceptSelf.productExceptSelf(a))); - } -} diff --git a/src/main/java/ds/RepeatInArray.java b/src/main/java/ds/RepeatInArray.java deleted file mode 100644 index d7478d9..0000000 --- a/src/main/java/ds/RepeatInArray.java +++ /dev/null @@ -1,77 +0,0 @@ -package ds; - -import java.util.ArrayList; -import java.util.List; - -/** - * 给定一个整数数组 a,其中1 ≤ a[i] ≤ n (n为数组长度), 其中有些元素出现两次而其他元素出现一次。 - *

- * 找到所有出现两次的元素。 - *

- * 你可以不用到任何额外空间并在O(n)时间复杂度内解决这个问题吗? - *

- *

- *

- * 思路: - * 1. 不能用额外空间,开辟散列表装数据的方法没戏。 - * 2. 时间复杂度为O(n),排序没戏。 - * - * @author yangyi 2019年02月08日10:13:40 - */ -public class RepeatInArray { - -// public List findDuplicates(int[] nums) { -// List targets = new ArrayList(); -// if (nums == null || nums.length == 0) { -// return new ArrayList(); -// } -// for (int i = 0; i < nums.length; i++) { -// if (nums[i] < 0 || nums[i]> nums.length - 1) { -// return new ArrayList(); -// } -// } -// for (int i = 0; i < nums.length; i++) { -// //如果当前元素不等于其索引,则交换 -// while (nums[i] != i) { -// -// //此处为结果的收集,异常重要,不能为了交换而交换 -// //如果当前元素等于当前元素作为索引值对应你的元素 -// if (nums[i] == nums[nums[i]]) { -// targets.add(nums[i]); -// } -// -// int temp = nums[i]; -// nums[i] = nums[temp]; -// nums[temp] = temp; -// } -// } -// return targets; -// } - - /** - * 时间复杂度:O(n) - * 空间复杂度:O(1) - *

- * 虽然效率爆表,但是也有弊端,因为改变了数组的顺序,如果题目不要求效率转而要求数组的结构不变,则此方法不适用。 - */ - public List findDuplicates(int[] nums) { - List result = new ArrayList(); - for (int i = 0; i < nums.length; i++) { - int index = Math.abs(nums[i]) - 1; - nums[index] = -nums[index]; - if (nums[index]> 0) { - result.add(index + 1); - } - } - return result; - } - - public static void main(String[] args) { - int[] ints = {4, 3, 2, 7, 8, 2, 3, 1}; - RepeatInArray repeatInArray = new RepeatInArray(); - List result = repeatInArray.findDuplicates(ints); - for (Integer integer : result) { - System.out.println(integer); - } - } -} diff --git a/src/main/java/ds/RotateArray.java b/src/main/java/ds/RotateArray.java deleted file mode 100644 index d3df5c2..0000000 --- a/src/main/java/ds/RotateArray.java +++ /dev/null @@ -1,70 +0,0 @@ -package ds; - -import java.util.Arrays; - -/** - * 旋转数组 - *

- *

- *

- * 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。 - *

- * 示例 1: - *

- * 输入: [1,2,3,4,5,6,7] 和 k = 3 - * 输出: [5,6,7,1,2,3,4] - * 解释: - * 向右旋转 1 步: [7,1,2,3,4,5,6] - * 向右旋转 2 步: [6,7,1,2,3,4,5] - * 向右旋转 3 步: [5,6,7,1,2,3,4] - * 示例 2: - *

- * 输入: [-1,-100,3,99] 和 k = 2 - * 输出: [3,99,-1,-100] - * 解释: - * 向右旋转 1 步: [99,-1,-100,3] - * 向右旋转 2 步: [3,99,-1,-100] - * 说明: - *

- * 尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。 - * 要求使用空间复杂度为 O(1) 的原地算法。 - *

- *

- *

- * 总共分为3步: - *

- * 1. 数组整个旋转一遍 - * 2. 以k为界,k之前的元素旋转 - * 3. 以k为界,k后面的元素旋转 - * - * @author yangyi 2019年02月12日11:56:52 - */ -public class RotateArray { - - private static int[] a = {1, 2, 3, 4, 5, 6, 7}; - private static int[] b = {-1, -100, 3, 99}; - - public void rotate(int[] nums, int k) { - int len = nums.length; - k %= len; - reserve(nums, 0, len - 1); - reserve(nums, 0, k - 1); - reserve(nums, k, len - 1); - } - - public void reserve(int[] nums, int start, int end) { - while (start < end) { - int temp = nums[start]; - nums[start++] = nums[end]; - nums[end--] = temp; - } - } - - public static void main(String[] args) { - RotateArray rotateArray = new RotateArray(); - rotateArray.rotate(a,3); - rotateArray.rotate(b,2); - System.out.println(Arrays.toString(a)); - System.out.println(Arrays.toString(b)); - } -} diff --git a/src/main/java/ds/SortedSquares.java b/src/main/java/ds/SortedSquares.java deleted file mode 100644 index 19d9203..0000000 --- a/src/main/java/ds/SortedSquares.java +++ /dev/null @@ -1,51 +0,0 @@ -package ds; - -import java.util.Arrays; - -/** - * 有序数组的平方 - *

- *

- * 给定一个按非递减顺序排序的整数数组 A,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。 - *

- *

- *

- * 示例 1: - *

- * 输入:[-4,-1,0,3,10] - * 输出:[0,1,9,16,100] - * 示例 2: - *

- * 输入:[-7,-3,2,3,11] - * 输出:[4,9,9,49,121] - *

- *

- * 提示: - *

- * 1 <= A.length <= 10000 - * -10000 <= A[i] <= 10000 - * A 已按非递减顺序排序。 - * - * @author yangyi 2019年02月16日23:17:48 - */ -public class SortedSquares { - - public int[] sortedSquares(int[] A) { - if (A == null || A.length == 0) { - return new int[]{}; - } - for (int i = 0; i < A.length; i++) { - A[i] *= A[i]; - } - Arrays.sort(A); - return A; - } - - public static void main(String[] args) { - int[] a = {-4, -1, 0, 3, 10}; - int[] b = {-7, -3, 2, 3, 11}; - SortedSquares sortedSquares = new SortedSquares(); - System.out.println(Arrays.toString(sortedSquares.sortedSquares(a))); - System.out.println(Arrays.toString(sortedSquares.sortedSquares(b))); - } -} diff --git a/src/main/java/ds/array/leetcode189/Solution.java b/src/main/java/ds/array/leetcode189/Solution.java new file mode 100644 index 0000000..e8e6459 --- /dev/null +++ b/src/main/java/ds/array/leetcode189/Solution.java @@ -0,0 +1,43 @@ +package ds.array.leetcode189; + +import java.util.Arrays; + +/** + * 189. 轮转数组 + * https://leetcode.cn/problems/rotate-array/ + * 总共分为3步: + * 1. 数组整个旋转一遍 + * 2. 以k为界,k之前的元素旋转 + * 3. 以k为界,k后面的元素旋转 + * + * @author yangyi 2023年09月04日15:53:56 + */ +public class Solution { + + private static int[] a = {1, 2, 3, 4, 5, 6, 7}; + private static int[] b = {-1, -100, 3, 99}; + + public void rotate(int[] nums, int k) { + int len = nums.length; + k %= len; + reserve(nums, 0, len - 1); + reserve(nums, 0, k - 1); + reserve(nums, k, len - 1); + } + + public void reserve(int[] nums, int start, int end) { + while (start < end) { + int temp = nums[start]; + nums[start++] = nums[end]; + nums[end--] = temp; + } + } + + public static void main(String[] args) { + Solution rotateArray = new Solution(); + rotateArray.rotate(a, 3); + rotateArray.rotate(b, 2); + System.out.println(Arrays.toString(a)); + System.out.println(Arrays.toString(b)); + } +} diff --git a/src/main/java/ds/ContainsNearbyDuplicate.java b/src/main/java/ds/array/leetcode219/Solution.java similarity index 57% rename from src/main/java/ds/ContainsNearbyDuplicate.java rename to src/main/java/ds/array/leetcode219/Solution.java index 7c9d369..dcdacbe 100644 --- a/src/main/java/ds/ContainsNearbyDuplicate.java +++ b/src/main/java/ds/array/leetcode219/Solution.java @@ -1,24 +1,12 @@ -package ds; - -import java.util.Arrays; +package ds.array.leetcode219; /** - * 给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的绝对值最大为 k。 - *

- * 示例 1: - *

- * 输入: nums = [1,2,3,1], k = 3 - * 输出: true - * 示例 2: - *

- * 输入: nums = [1,0,1,1], k = 1 - * 输出: true - * 示例 3: - *

- * 输入: nums = [1,2,3,1,2,3], k = 2 - * 输出: false + * 219. 存在重复元素 II + * https://leetcode.cn/problems/contains-duplicate-ii/description/ + * + * @author yangyi 2023年09月04日18:03:26 */ -public class ContainsNearbyDuplicate { +public class Solution { public boolean containsNearbyDuplicate(int[] nums, int k) { for (int i = 0; i < nums.length; i++) { @@ -35,7 +23,7 @@ public static void main(String[] args) { int[] nums_1 = {1, 2, 3, 1}; int[] nums_2 = {1, 0, 1, 1}; int[] nums_3 = {1, 2, 3, 1, 2, 3}; - ContainsNearbyDuplicate containsNearbyDuplicate = new ContainsNearbyDuplicate(); + Solution containsNearbyDuplicate = new Solution(); System.out.println(containsNearbyDuplicate.containsNearbyDuplicate(nums_1, 3)); System.out.println(containsNearbyDuplicate.containsNearbyDuplicate(nums_2, 1)); System.out.println(containsNearbyDuplicate.containsNearbyDuplicate(nums_3, 2)); diff --git a/src/main/java/ds/array/leetcode238/Solution.java b/src/main/java/ds/array/leetcode238/Solution.java new file mode 100644 index 0000000..d63b682 --- /dev/null +++ b/src/main/java/ds/array/leetcode238/Solution.java @@ -0,0 +1,34 @@ +package ds.array.leetcode238; + +import java.util.Arrays; + +/** + * 238. 除自身以外数组的乘积 + * https://leetcode.cn/problems/product-of-array-except-self/ + * + * @author yangyi 2023年09月04日17:31:30 + */ +public class Solution { + + public int[] productExceptSelf(int[] nums) { + int left = 1; + int right = 1; + int len = nums.length; + int[] output = new int[len]; + for (int i = 0; i < len; i++) { + output[i] = left; + left *= nums[i]; + } + for (int j = len - 1; j>= 0; j--) { + output[j] *= right; + right *= nums[j]; + } + return output; + } + + public static void main(String[] args) { + int[] a = {1,2,3,4}; + Solution productExceptSelf = new Solution(); + System.out.println(Arrays.toString(productExceptSelf.productExceptSelf(a))); + } +} diff --git a/src/main/java/ds/IncreasingTriplet.java b/src/main/java/ds/array/leetcode334/Solution.java similarity index 52% rename from src/main/java/ds/IncreasingTriplet.java rename to src/main/java/ds/array/leetcode334/Solution.java index 30a2fb2..ad7c461 100644 --- a/src/main/java/ds/IncreasingTriplet.java +++ b/src/main/java/ds/array/leetcode334/Solution.java @@ -1,31 +1,12 @@ -package ds; +package ds.array.leetcode334; /** - * 递增的三元子序列 - *

- *

- *

- *

- * 给定一个未排序的数组,判断这个数组中是否存在长度为 3 的递增子序列。 - *

- * 数学表达式如下: - *

- * 如果存在这样的 i, j, k, 且满足 0 ≤ i < j < k ≤ n-1, - * 使得 arr[i] < arr[j] < arr[k] ,返回 true ; 否则返回 false 。 - * 说明: 要求算法的时间复杂度为 O(n),空间复杂度为 O(1) 。 - *

- * 示例 1: - *

- * 输入: [1,2,3,4,5] - * 输出: true - * 示例 2: - *

- * 输入: [5,4,3,2,1] - * 输出: false + * 334. 递增的三元子序列 + * https://leetcode.cn/problems/increasing-triplet-subsequence/ * * @author yangyi 2019年03月02日22:45:15 */ -public class IncreasingTriplet { +public class Solution { public boolean increasingTriplet(int[] nums) { int min = Integer.MAX_VALUE; @@ -45,7 +26,7 @@ public boolean increasingTriplet(int[] nums) { public static void main(String[] args) { int[] a = {1,2,3,4,5}; int[] b = {5,4,3,2,1}; - IncreasingTriplet increasingTriplet = new IncreasingTriplet(); + Solution increasingTriplet = new Solution(); System.out.println(increasingTriplet.increasingTriplet(a)); System.out.println(increasingTriplet.increasingTriplet(b)); } diff --git a/src/main/java/ds/Intersect.java b/src/main/java/ds/array/leetcode350/Solution.java similarity index 55% rename from src/main/java/ds/Intersect.java rename to src/main/java/ds/array/leetcode350/Solution.java index 561c98f..6d33a91 100644 --- a/src/main/java/ds/Intersect.java +++ b/src/main/java/ds/array/leetcode350/Solution.java @@ -1,39 +1,14 @@ -package ds; +package ds.array.leetcode350; import java.util.*; /** - * 两个数组的交集 II - *

- *

- * 给定两个数组,编写一个函数来计算它们的交集。 - *

- * 示例 1: - *

- * 输入: nums1 = [1,2,2,1], nums2 = [2,2] - * 输出: [2,2] - * 示例 2: - *

- * 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4] - * 输出: [4,9] - *

- *

- * ------------------------------------------------- - *

- *

- * 说明: - *

- * 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。 - * 我们可以不考虑输出结果的顺序。 - * 进阶: - *

- * 如果给定的数组已经排好序呢?你将如何优化你的算法? - * 如果 nums1 的大小比 nums2 小很多,哪种方法更优? - * 如果 nums2 的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办? + * 350. 两个数组的交集 II + * https://leetcode.cn/problems/intersection-of-two-arrays-ii/description/ * - * @author yangyi 2019年03月02日22:00:51 + * @author yangyi 2023年09月04日17:17:39 */ -public class Intersect { +public class Solution { public int[] intersect(int[] nums1, int[] nums2) { //key为数字,value为次数 @@ -60,7 +35,7 @@ public int[] intersect(int[] nums1, int[] nums2) { } public static void main(String[] args) { - Intersect intersect = new Intersect(); + Solution intersect = new Solution(); int[] a = {1, 2, 2, 1}; int[] b = {2, 2}; int[] a2 = {4, 9, 5}; diff --git a/src/main/java/ds/array/leetcode442/Solution.java b/src/main/java/ds/array/leetcode442/Solution.java new file mode 100644 index 0000000..baf62db --- /dev/null +++ b/src/main/java/ds/array/leetcode442/Solution.java @@ -0,0 +1,43 @@ +package ds.array.leetcode442; + +import java.util.ArrayList; +import java.util.List; + +/** + * 442. 数组中重复的数据 + * https://leetcode.cn/problems/find-all-duplicates-in-an-array/ + * 思路: + * 1. 不能用额外空间,开辟散列表装数据的方法没戏。 + * 2. 时间复杂度为O(n),排序没戏。 + * + * @author yangyi 2023年09月04日11:30:43 + */ +public class Solution { + + /** + * 时间复杂度:O(n) + * 空间复杂度:O(1) + *

+ * 虽然效率爆表,但是也有弊端,因为改变了数组的顺序,如果题目不要求效率转而要求数组的结构不变,则此方法不适用。 + */ + public List findDuplicates(int[] nums) { + List result = new ArrayList(); + for (int i = 0; i < nums.length; i++) { + int index = Math.abs(nums[i]) - 1; + nums[index] = -nums[index]; + if (nums[index]> 0) { + result.add(index + 1); + } + } + return result; + } + + public static void main(String[] args) { + int[] ints = {4, 3, 2, 7, 8, 2, 3, 1}; + Solution repeatInArray = new Solution(); + List result = repeatInArray.findDuplicates(ints); + for (Integer integer : result) { + System.out.println(integer); + } + } +} diff --git a/src/main/java/ds/array/leetcode724/Solution.java b/src/main/java/ds/array/leetcode724/Solution.java new file mode 100644 index 0000000..65c7a1d --- /dev/null +++ b/src/main/java/ds/array/leetcode724/Solution.java @@ -0,0 +1,41 @@ +package ds.array.leetcode724; + +import java.util.Arrays; + +/** + * 724. 寻找数组的中心下标 + * https://leetcode.cn/problems/find-pivot-index/ + * + * @author yangyi 2023年09月04日16:43:00 + */ +public class Solution { + + public int pivotIndex(int[] nums) { + int sum = 0; + int leftSum = 0; + int rightSum = 0; + for (int i = 0; i < nums.length; i++) { + sum += nums[i]; + } + for (int i = 0; i < nums.length; i++) { + rightSum = sum - leftSum - nums[i]; + if (leftSum == rightSum) { + return i; + } + leftSum += nums[i]; + } + return -1; + } + + public static void main(String[] args) { + int[] a = {1, 7, 3, 6, 5, 6}; + int[] b = {1, 2, 3}; + int[] c = {-1, -1, 0, 1, 0, -1}; + int[] d = {-1, -1, 0, 1, 1, 0}; + Solution pivotIndex = new Solution(); + System.out.println(Arrays.toString(a) + "的中心索引是:" + pivotIndex.pivotIndex(a)); + System.out.println(Arrays.toString(b) + "的中心索引是:" + pivotIndex.pivotIndex(b)); + System.out.println(Arrays.toString(c) + "的中心索引是:" + pivotIndex.pivotIndex(c)); + System.out.println(Arrays.toString(d) + "的中心索引是:" + pivotIndex.pivotIndex(d)); + } +} diff --git a/src/main/java/ds/FindInDoubleArray.java b/src/main/java/ds/array/leetcode74/Solution.java similarity index 81% rename from src/main/java/ds/FindInDoubleArray.java rename to src/main/java/ds/array/leetcode74/Solution.java index e6741e8..9b8d28d 100644 --- a/src/main/java/ds/FindInDoubleArray.java +++ b/src/main/java/ds/array/leetcode74/Solution.java @@ -1,17 +1,12 @@ -package ds; +package ds.array.leetcode74; /** - * 前提: 二维数组是一个从左至右边递增,从上至下递增。 - *

- * 方法: - *

- * 1. 从二维数组右上角的元素开始find循环查询,并以右上角元素为基准点。 - * 2. 如果要查询的元素比基准点小,基准点向左移。 - * 3. 如果要查询的元素比基准点大,基准点向下移。 + * 74. 搜索二维矩阵 + * https://leetcode.cn/problems/search-a-2d-matrix/ * - * @author yangyi 2019年02月08日09:20:55 + * @author yangyi 2023年09月04日11:14:35 */ -public class FindInDoubleArray { +public class Solution { /** * @param matrix 待查找的目标二维数组 @@ -60,7 +55,7 @@ public static void main(String[] args) { } System.out.println(); } - FindInDoubleArray findInDoubleArray = new FindInDoubleArray(); + Solution findInDoubleArray = new Solution(); int target1 = 6; int target2 = 8; int target3 = 0; diff --git a/src/main/java/ds/array/leetcode88/Solution.java b/src/main/java/ds/array/leetcode88/Solution.java new file mode 100644 index 0000000..faf3f7d --- /dev/null +++ b/src/main/java/ds/array/leetcode88/Solution.java @@ -0,0 +1,28 @@ +package ds.array.leetcode88; + +import java.util.Arrays; + +/** + * 88.合并两个有序数组 + * https://leetcode.cn/problems/merge-sorted-array/ + * + * @author yangyi 2023年09月04日15:27:42 + */ +public class Solution { + + public void merge(int[] nums1, int m, int[] nums2, int n) { + for (int i = 0; i < n; i++) { + nums1[m + i] = nums2[i]; + } + Arrays.sort(nums1); + } + + public static void main(String[] args) { + int[] nums1 = {1, 2, 3, 0, 0, 0}; + int[] nums2 = {2, 5, 6}; + new Solution().merge(nums1, 3, nums2, 3); + System.out.println(Arrays.toString(nums1)); + System.out.println(Arrays.toString(nums2)); + } + +} diff --git a/src/main/java/ds/array/leetcode977/Solution.java b/src/main/java/ds/array/leetcode977/Solution.java new file mode 100644 index 0000000..6670f15 --- /dev/null +++ b/src/main/java/ds/array/leetcode977/Solution.java @@ -0,0 +1,31 @@ +package ds.array.leetcode977; + +import java.util.Arrays; + +/** + * 977. 有序数组的平方 + * https://leetcode.cn/problems/squares-of-a-sorted-array/ + * + * @author yangyi 2023年09月04日16:37:38 + */ +public class Solution { + + public int[] sortedSquares(int[] nums) { + if (nums == null || nums.length == 0) { + return new int[]{}; + } + for (int i = 0; i < nums.length; i++) { + nums[i] *= nums[i]; + } + Arrays.sort(nums); + return nums; + } + + public static void main(String[] args) { + int[] a = {-4, -1, 0, 3, 10}; + int[] b = {-7, -3, 2, 3, 11}; + Solution sortedSquares = new Solution(); + System.out.println(Arrays.toString(sortedSquares.sortedSquares(a))); + System.out.println(Arrays.toString(sortedSquares.sortedSquares(b))); + } +} diff --git a/src/main/java/ds/dfs/leetcode129/Solution.java b/src/main/java/ds/dfs/leetcode129/Solution.java new file mode 100644 index 0000000..475dc2b --- /dev/null +++ b/src/main/java/ds/dfs/leetcode129/Solution.java @@ -0,0 +1,54 @@ +package ds.dfs.leetcode129; + +/** + * 129. 求根节点到叶节点数字之和 + * https://leetcode.cn/problems/sum-root-to-leaf-numbers/description/?envType=study-plan-v2&envId=top-interview-150 + * + * @author yangyi 2023年09月04日01:32:43 + */ +class Solution { + + public static class TreeNode { + int val; + TreeNode left; + TreeNode right; + + TreeNode() { + } + + TreeNode(int val) { + this.val = val; + } + + TreeNode(int val, TreeNode left, TreeNode right) { + this.val = val; + this.left = left; + this.right = right; + } + } + + public int sumNumbers(TreeNode root) { + return sumNumbersDfs(root, 0); + } + + public int sumNumbersDfs(TreeNode root, int preSum) { + if (root == null) { + return 0; + } + int sum = preSum * 10 + root.val; + if (root.left == null && root.right == null) { + return sum; + } else { + return sumNumbersDfs(root.left, sum) + sumNumbersDfs(root.right, sum); + } + } + + public static void main(String[] args) { + TreeNode one = new TreeNode(1); + TreeNode two = new TreeNode(2); + TreeNode three = new TreeNode(3); + one.left = two; + one.right = three; + System.out.println(new Solution().sumNumbers(one)); + } +} diff --git a/src/main/java/ds/dp/leetcode322/Solution.java b/src/main/java/ds/dp/leetcode322/Solution.java new file mode 100644 index 0000000..666e6ba --- /dev/null +++ b/src/main/java/ds/dp/leetcode322/Solution.java @@ -0,0 +1,35 @@ +package ds.dp.leetcode322; + +/** + * 322. 零钱兑换 + * https://leetcode.cn/problems/coin-change/description/ + * + * @author yangyi 2023年09月13日00:54:39 + */ +class Solution { + + public int coinChange(int[] coins, int amount) { + if (amount == 0) { + return 0; + } + int[] dp = new int[amount + 1]; + for (int i = 1; i <= amount; i++) { + dp[i] = 999999; + for (int coin : coins) { + if (i - coin < 0) { + continue; + } + dp[i] = Math.min(dp[i], dp[i - coin] + 1); + } + } + return dp[amount] == 999999 ? -1 : dp[amount]; + } + + public static void main(String[] args) { + System.out.println(new Solution().coinChange(new int[]{1, 2, 5}, 11)); + System.out.println(new Solution().coinChange(new int[]{2}, 3)); + System.out.println(new Solution().coinChange(new int[]{1}, 0)); + } + + +} diff --git a/src/main/java/ds/dp/leetcode64/Solution.java b/src/main/java/ds/dp/leetcode64/Solution.java new file mode 100644 index 0000000..715e987 --- /dev/null +++ b/src/main/java/ds/dp/leetcode64/Solution.java @@ -0,0 +1,33 @@ +package ds.dp.leetcode64; + +/** + * 64. 最小路径和 + * https://leetcode.cn/problems/minimum-path-sum/description/?envType=study-plan-v2&envId=xiaohongshu-2023-fall-sprint + * + * @author yangyi 2023年09月03日21:36:30 + */ +class Solution { + + public int minPathSum(int[][] grid) { + int[][] dp = new int[grid.length][grid[0].length]; + for (int i = grid.length - 1; i>= 0; i--) { + for (int j = grid[0].length - 1; j>= 0; j--) { + if (i == grid.length - 1 && j != grid[0].length - 1) { + dp[i][j] = grid[i][j] + dp[i][j + 1]; + } else if (i != grid.length - 1 && j == grid[0].length - 1) { + dp[i][j] = grid[i][j] + dp[i + 1][j]; + } else if (i != grid.length - 1 && j != grid[0].length - 1) { + dp[i][j] = grid[i][j] + Math.min(dp[i][j + 1], dp[i + 1][j]); + } else { + dp[i][j] = grid[i][j]; + } + } + } + return dp[0][0]; + } + + public static void main(String[] args) { + int[][] origin = {{1, 3, 1}, {1, 5, 1}, {4, 2, 1}}; + System.out.println(new Solution().minPathSum(origin)); + } +} diff --git a/src/main/java/ds/hashmap/leetcode409/Solution.java b/src/main/java/ds/hashmap/leetcode409/Solution.java new file mode 100644 index 0000000..6e73e4d --- /dev/null +++ b/src/main/java/ds/hashmap/leetcode409/Solution.java @@ -0,0 +1,31 @@ +package ds.hashmap.leetcode409; + +import java.util.HashSet; + +/** + * 409. 最长回文串 + * https://leetcode.cn/problems/longest-palindrome/description/ + * + * @author yangyi 2023年09月03日22:38:14 + */ +class Solution { + + public int longestPalindrome(String s) { + HashSet set = new HashSet(); + for (int i = 0; i < s.length(); i++) { + if (set.contains(s.charAt(i))) { + set.remove(s.charAt(i)); + } else { + set.add(s.charAt(i)); + } + } + // 先全部减掉然后再挑一个构成回文串最中间的对称轴 + return set.size() == 0 ? s.length() : s.length() - set.size() + 1; + } + + public static void main(String[] args) { + System.out.println(new Solution().longestPalindrome("abccccdd")); + System.out.println(new Solution().longestPalindrome("a")); + System.out.println(new Solution().longestPalindrome("aaaaaccc")); + } +} diff --git a/src/main/java/ds/pointer/leetcode19/Solution.java b/src/main/java/ds/pointer/leetcode19/Solution.java new file mode 100644 index 0000000..8ecf528 --- /dev/null +++ b/src/main/java/ds/pointer/leetcode19/Solution.java @@ -0,0 +1,66 @@ +package ds.pointer.leetcode19; + +/** + * 19.删除链表的倒数第N个节点 + * https://leetcode.cn/problems/remove-nth-node-from-end-of-list/solutions/450350/shan-chu-lian-biao-de-dao-shu-di-nge-jie-dian-b-61/?envType=study-plan-v2&envId=xiaohongshu-2023-fall-sprint + * + * @author yangyi 2023年09月03日23:04:36 + */ +class Solution { + + 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 ListNode removeNthFromEnd(ListNode head, int n) { + if (head == null) { + return null; + } + ListNode soldier = new ListNode(0); + soldier.next = head; + ListNode slow = soldier; + ListNode fast = soldier; + while (fast.next != null) { + n--; + fast = fast.next; + if (n == 0) { + break; + } + } + while (fast.next != null) { + slow = slow.next; + fast = fast.next; + } + slow.next = slow.next.next; + return soldier.next; + } + + public static void main(String[] args) { + ListNode one = new ListNode(1); + ListNode two = new ListNode(2); + ListNode three = new ListNode(3); + ListNode four = new ListNode(4); + ListNode five = new ListNode(5); + one.next = two; + two.next = three; + three.next = four; + four.next = five; + ListNode res = new Solution().removeNthFromEnd(one, 2); + for (ListNode cur = res; cur != null; cur = cur.next) { + System.out.println(cur.val); + } + } +} diff --git a/src/main/java/ds/pointer/leetcode252/Solution.java b/src/main/java/ds/pointer/leetcode252/Solution.java new file mode 100644 index 0000000..b89778a --- /dev/null +++ b/src/main/java/ds/pointer/leetcode252/Solution.java @@ -0,0 +1,39 @@ +package ds.pointer.leetcode252; + +import java.util.Arrays; + +/** + * 252.会议室 + * https://leetcode.cn/problems/meeting-rooms/ + * + * @author yangyi 2023年09月12日22:31:53 + */ +class Solution { + + public boolean canAttendMeetings(int[][] intervals) { + int n = intervals.length; + int[] start = new int[n]; + int[] end = new int[n]; + for (int i = 0; i < n; i++) { + start[i] = intervals[i][0]; + end[i] = intervals[i][1]; + } + Arrays.sort(start); + Arrays.sort(end); + int i = 0; + while (i < n - 1) { + if (start[i + 1] < end[i]) { + return false; + } + i++; + } + return true; + } + + public static void main(String[] args) { + int[][] res = {{0, 30}, {5, 10}, {15, 20}}; + int[][] res2 = {{7, 10}, {2, 4}}; + System.out.println(new Solution().canAttendMeetings(res)); + System.out.println(new Solution().canAttendMeetings(res2)); + } +} diff --git a/src/main/java/ds/pointer/leetcode253/Solution.java b/src/main/java/ds/pointer/leetcode253/Solution.java new file mode 100644 index 0000000..9bcd5d7 --- /dev/null +++ b/src/main/java/ds/pointer/leetcode253/Solution.java @@ -0,0 +1,44 @@ +package ds.pointer.leetcode253; + +import java.util.Arrays; + +/** + * 253. 会议室 II + * https://leetcode.cn/problems/meeting-rooms-ii/ + * + * @author yangyi 2023年09月12日23:15:50 + */ +class Solution { + + public int minMeetingRooms(int[][] intervals) { + int n = intervals.length; + int[] start = new int[n]; + int[] end = new int[n]; + for (int i = 0; i < n; i++) { + start[i] = intervals[i][0]; + end[i] = intervals[i][1]; + } + Arrays.sort(start); + Arrays.sort(end); + int result = 0, count = 0; + int i = 0, j = 0; + while (i < n && j < n) { + if (start[i] < end[j]) { + count++; + i++; + } else { + count--; + j++; + } + result = Math.max(result, count); + } + return result; + } + + public static void main(String[] args) { + int[][] res = {{0, 30}, {5, 10}, {15, 20}}; + int[][] res2 = {{7, 10}, {2, 4}}; + System.out.println(new Solution().minMeetingRooms(res)); + System.out.println(new Solution().minMeetingRooms(res2)); + } +}

AltStyle によって変換されたページ (->オリジナル) /