diff --git a/week01/Class3$climbStairs.java b/week01/Class3$climbStairs.java new file mode 100644 index 00000000..39e1fedc --- /dev/null +++ b/week01/Class3$climbStairs.java @@ -0,0 +1,64 @@ +//假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 +// +// 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? +// +// 注意:给定 n 是一个正整数。 +// +// 示例 1: +// +// 输入: 2 +//输出: 2 +//解释: 有两种方法可以爬到楼顶。 +//1. 1 阶 + 1 阶 +//2. 2 阶 +// +// 示例 2: +// +// 输入: 3 +//输出: 3 +//解释: 有三种方法可以爬到楼顶。 +//1. 1 阶 + 1 阶 + 1 阶 +//2. 1 阶 + 2 阶 +//3. 2 阶 + 1 阶 +// +// Related Topics 动态规划 + + +//leetcode submit region begin(Prohibit modification and deletion) +class Class3$climbStairs { + // 1.fibonacci 递归 + /*public int climbStairs(int n) { + if (n <= 2) { + return n; + } + return climbStairs(n - 1) + climbStairs(n - 2); + }*/ + + // 2.fibonacci 循环 + /*public int climbStairs(int n) { + if (n <= 2) { + return n; + } + int first = 1; + int second = 2; + for (int i = 3; i <= n; i++) { + int third = first + second; + first = second; + second = third; + } + return second; + }*/ + + // 3.滚动数组 + public int climbStairs(int n) { + int q = 0, p = 0, r = 1; + for (int i = 1; i <= n; i++) { + q = p; + p = r; + r = q + p; + } + return r; + } + +} +//leetcode submit region end(Prohibit modification and deletion) diff --git a/week01/Class3$maxArea.java b/week01/Class3$maxArea.java new file mode 100644 index 00000000..208e6ceb --- /dev/null +++ b/week01/Class3$maxArea.java @@ -0,0 +1,50 @@ +//给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, +//ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 +// +// 说明:你不能倾斜容器,且 n 的值至少为 2。 +// +// +// +// +// +// 图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。 +// +// +// +// 示例: +// +// 输入:[1,8,6,2,5,4,8,3,7] +//输出:49 +// Related Topics 数组 双指针 + + +//leetcode submit region begin(Prohibit modification and deletion) +class Class3$maxArea { + + // 1. 两层循环,获取每两个柱子之间的容纳量,获取最大值 + /*public int maxArea(int[] height) { + int max = 0; + // i循环没有必要获取最后一个数字,因为是求两个不通位置数字 + for (int i = 0; i < height.length - 1; i++) { + for (int j = i + 1; j < height.length; j++) { + int area = (j - i) * Math.min(height[i], height[j]); + max = Math.max(max, area); + } + } + return max; + }*/ + + // 2,两个下标,找中间的最大值 + public int maxArea(int[] height) { + int max = 0; + for (int i = 0, j = height.length - 1; i < j;) { + // 谁短就取谁,取完往内部收敛 + int minHeight = height[i] < height[j] ? height[i++] : height[j--]; + // 上一句已经进行了i/j的移位,这里要加回去算大小 + int area = (j - i + 1) * minHeight; + max = Math.max(max, area); + } + return max; + } +} +//leetcode submit region end(Prohibit modification and deletion) diff --git a/week01/Class3$moveZeroes.java b/week01/Class3$moveZeroes.java new file mode 100644 index 00000000..fae80d91 --- /dev/null +++ b/week01/Class3$moveZeroes.java @@ -0,0 +1,69 @@ +//给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 +// +// 示例: +// +// 输入: [0,1,0,3,12] +//输出: [1,3,12,0,0] +// +// 说明: +// +// +// 必须在原数组上操作,不能拷贝额外的数组。 +// 尽量减少操作次数。 +// +// Related Topics 数组 双指针 + + +import java.util.Arrays; + +//leetcode submit region begin(Prohibit modification and deletion) +class Class3$moveZeroes { + // 1 两层循环 + /*public void moveZeroes(int[] nums) { + long zeroNumSize = Arrays.stream(nums).filter(num -> num == 0).count(); + long size = 0; + for (int i = 0; i < nums.length;) { + if (nums[i] == 0) { + if (size++ >= zeroNumSize) { + break; + } + // 移动到最后,后面的左移 + for (int j = i + 1; j < nums.length; j++) { + nums[j - 1] = nums[j]; + } + nums[nums.length - 1] = 0; + continue; + } + i++; + } + }*/ + + // 2 新建数组,非0在前,0在后,依次放入 + /*public void moveZeroes(int[] nums) { + int[] elements = new int[nums.length]; + int start = 0; + int end = elements.length - 1; + for (int i = 0; i < nums.length; i++) { + if (nums[i] != 0) { + elements[start++] = nums[i]; + } else { + elements[end--] = nums[i]; + } + } + }*/ + + // 3 单循环,使用j记录非0数字所在位置 + public void moveZeroes(int[] nums) { + int j = 0; + for (int i = 0; i < nums.length; i++) { + if (nums[i] != 0) { + nums[j] = nums[i]; + if (i != j) { + nums[i] = 0; + } + j++; + } + } + } +} +//leetcode submit region end(Prohibit modification and deletion) diff --git a/week01/Class3$reverseList.java b/week01/Class3$reverseList.java new file mode 100644 index 00000000..8d6c7a72 --- /dev/null +++ b/week01/Class3$reverseList.java @@ -0,0 +1,47 @@ +//反转一个单链表。 +// +// 示例: +// +// 输入: 1->2->3->4->5->NULL +//输出: 5->4->3->2->1->NULL +// +// 进阶: +//你可以迭代或递归地反转链表。你能否用两种方法解决这道题? +// Related Topics 链表 + + +//leetcode submit region begin(Prohibit modification and deletion) +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { val = x; } + * } + */ +class Class3$reverseList { + // 1.多用一个头 + /*public ListNode reverseList(ListNode head) { + ListNode result = new ListNode(0); + while (head != null) { + ListNode temp = head.next; + head.next = result.next; + result.next = head; + head = temp; + } + return result.next; + }*/ + + // 2. + public ListNode reverseList(ListNode head) { + ListNode result = null; + while (head != null) { + ListNode temp = head.next; + head.next = result; + result = head; + head = temp; + } + return result; + } +} +//leetcode submit region end(Prohibit modification and deletion) diff --git a/week01/Class3$threeSum.java b/week01/Class3$threeSum.java new file mode 100644 index 00000000..53fbda27 --- /dev/null +++ b/week01/Class3$threeSum.java @@ -0,0 +1,133 @@ +//给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复 +//的三元组。 +// +// 注意:答案中不可以包含重复的三元组。 +// +// +// +// 示例: +// +// 给定数组 nums = [-1, 0, 1, 2, -1, -4], +// +//满足要求的三元组集合为: +//[ +// [-1, 0, 1], +// [-1, -1, 2] +//] +// +// Related Topics 数组 双指针 + + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +//leetcode submit region begin(Prohibit modification and deletion) +class Class3$threeSum { + + // 1.三层循环 + /*public List> threeSum(int[] nums) { + Set> set = new LinkedHashSet<>(); + for (int i = 0; i < nums.length - 2; i++) { + for (int j = i + 1; j < nums.length - 1; j++) { + for (int k = j + 1; k < nums.length; k++) { + if ((nums[i] + nums[j] + nums[k]) == 0) { + List result = Arrays.asList(nums[i], nums[j], nums[k]); + result.sort(Comparator.naturalOrder()); + set.add(result); + } + } + } + } + return new ArrayList(set); + }*/ + + // 2.hash 两层循环 + /*public List> threeSum(int[] nums) { + Set> set = new LinkedHashSet<>(); + Map map = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + map.put(0 - nums[i], i); + } + for (int i = 0; i < nums.length - 1; i++) { + for (int j = i + 1; j < nums.length; j++) { + Integer temp = map.get(nums[i] + nums[j]); + if (temp != null && temp > i && temp > j) { + List result = Arrays.asList(nums[i], nums[j], 0 - nums[i] - nums[j]); + result.sort(Comparator.naturalOrder()); + set.add(result); + } + } + } + return new ArrayList(set); + }*/ + + // 3.排序夹逼 + /*public List> threeSum(int[] nums) { + Arrays.sort(nums); + List> list = new ArrayList<>(); + for (int i = 0; i < nums.length - 2; i++) { + if (nums[i] > 0) { + continue; + } + if (i > 0 && nums[i] == nums[i - 1]) { + continue; + } + for (int j = i + 1, k = nums.length - 1; j < k;) { + if (j > i + 1 && nums[j] == nums[j - 1]) { + j++; + continue; + } + if (k < nums.length - 1 && nums[k] == nums[k + 1]) { + k--; + continue; + } + int temp = nums[i] + nums[j] + nums[k]; + if (temp == 0) { + list.add(Arrays.asList(nums[i], nums[j], nums[k])); + j++; + k--; + } else if (temp < 0) { + j++; + } else { + k--; + } + } + } + return list; + }*/ + + // 4.更简洁 + public List> threeSum(int[] nums) { + Arrays.sort(nums); + List> list = new ArrayList<>(); + for (int i = 0; i < nums.length - 2; i++) { + if (nums[i] > 0) { + continue; + } + if (i > 0 && nums[i] == nums[i - 1]) { + continue; + } + int j = i + 1, k = nums.length - 1; + while (j < k) { + int sum = nums[i] + nums[j] + nums[k]; + if (sum < 0) { + while (j < k && nums[j] == nums[++j]); + } else if (sum > 0) { + while (j < k && nums[k] == nums[--k]); + } else { + list.add(Arrays.asList(nums[i], nums[j], nums[k])); + while (j < k && nums[j] == nums[++j]); + while (j < k && nums[k] == nums[--k]); + } + } + } + return list; + } +} +//leetcode submit region end(Prohibit modification and deletion) diff --git a/week01/Class3$twoSum.java b/week01/Class3$twoSum.java new file mode 100644 index 00000000..b7d93d38 --- /dev/null +++ b/week01/Class3$twoSum.java @@ -0,0 +1,32 @@ +//给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 +// +// 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。 +// +// +// +// 示例: +// +// 给定 nums = [2, 7, 11, 15], target = 9 +// +//因为 nums[0] + nums[1] = 2 + 7 = 9 +//所以返回 [0, 1] +// +// Related Topics 数组 哈希表 + + +import java.util.HashMap; + +//leetcode submit region begin(Prohibit modification and deletion) +class Class3$twoSum { + public int[] twoSum(int[] nums, int target) { + Map map = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + if (map.containsKey(target - nums[i]) ) { + return new int[] {map.get(target - nums[i]), i}; + } + map.put(nums[i], i); + } + return null; + } +} +//leetcode submit region end(Prohibit modification and deletion)