From eeeb2cf53b0c73c7d11e66446f9920779acb34cd Mon Sep 17 00:00:00 2001 From: unknown <363595819@qq.com> Date: Sun, 14 Jun 2020 22:10:19 +0800 Subject: [PATCH 1/5] week01 task commit by luman 20200614 --- Week01/DesignCircularDeque.java | 141 ++++++++++++++++++++++++++++++++ Week01/NOTE.md | 41 +++++++++- Week01/ReverseLinkedList.java | 45 ++++++++++ Week01/ThreeSum.java | 67 +++++++++++++++ Week01/TrappingRainWater.java | 43 ++++++++++ 5 files changed, 336 insertions(+), 1 deletion(-) create mode 100644 Week01/DesignCircularDeque.java create mode 100644 Week01/ReverseLinkedList.java create mode 100644 Week01/ThreeSum.java create mode 100644 Week01/TrappingRainWater.java diff --git a/Week01/DesignCircularDeque.java b/Week01/DesignCircularDeque.java new file mode 100644 index 000000000..31cab7017 --- /dev/null +++ b/Week01/DesignCircularDeque.java @@ -0,0 +1,141 @@ +//设计实现双端队列。 +//你的实现需要支持以下操作: +// +// +// MyCircularDeque(k):构造函数,双端队列的大小为k。 +// insertFront():将一个元素添加到双端队列头部。 如果操作成功返回 true。 +// insertLast():将一个元素添加到双端队列尾部。如果操作成功返回 true。 +// deleteFront():从双端队列头部删除一个元素。 如果操作成功返回 true。 +// deleteLast():从双端队列尾部删除一个元素。如果操作成功返回 true。 +// getFront():从双端队列头部获得一个元素。如果双端队列为空,返回 -1。 +// getRear():获得双端队列的最后一个元素。 如果双端队列为空,返回 -1。 +// isEmpty():检查双端队列是否为空。 +// isFull():检查双端队列是否满了。 +// +// +// 示例: +// +// MyCircularDeque circularDeque = new MycircularDeque(3); // 设置容量大小为3 +//circularDeque.insertLast(1); // 返回 true +//circularDeque.insertLast(2); // 返回 true +//circularDeque.insertFront(3); // 返回 true +//circularDeque.insertFront(4); // 已经满了,返回 false +//circularDeque.getRear(); // 返回 2 +//circularDeque.isFull(); // 返回 true +//circularDeque.deleteLast(); // 返回 true +//circularDeque.insertFront(4); // 返回 true +//circularDeque.getFront(); // 返回 4 +//  +// +// +// +// 提示: +// +// +// 所有值的范围为 [1, 1000] +// 操作次数的范围为 [1, 1000] +// 请不要使用内置的双端队列库。 +// +// Related Topics 设计 队列 + +package com.cute.leetcode.editor.cn; + + +public class DesignCircularDeque { + public static void main(String[] args) { + Solution solution = new DesignCircularDeque().new Solution(); + } + //leetcode submit region begin(Prohibit modification and deletion) +class MyCircularDeque { + int[] arr; + int right = 1; + + /** Initialize your data structure here. Set the size of the deque to be k. */ + public MyCircularDeque(int k) { + this.arr = new int[k+1]; + } + + /** Adds an item at the front of Deque. Return true if the operation is successful. */ + public boolean insertFront(int value) { + if (isFull()) { + return false; + } + //移动 + System.arraycopy(arr, 1, arr, 2, right - 1); + arr[1] = value; + right++; + return true; + } + + /** Adds an item at the rear of Deque. Return true if the operation is successful. */ + public boolean insertLast(int value) { + if (isFull()) { + return false; + } + arr[right++] = value; + return true; + } + + /** Deletes an item from the front of Deque. Return true if the operation is successful. */ + public boolean deleteFront() { + if (isEmpty()) { + return false; + } + //移动 + System.arraycopy(arr, 2, arr, 1, right - 2); + //arr[right] = 0; + right--; + return true; + } + + /** Deletes an item from the rear of Deque. Return true if the operation is successful. */ + public boolean deleteLast() { + if (isEmpty()) { + return false; + } + right--; + return true; + } + + /** Get the front item from the deque. */ + public int getFront() { + if (isEmpty()) { + return -1; + } + return arr[1]; + } + + /** Get the last item from the deque. */ + public int getRear() { + if (isEmpty()) { + return -1; + } + return arr[right-1]; + } + + /** Checks whether the circular deque is empty or not. */ + public boolean isEmpty() { + return right == 1; + } + + /** Checks whether the circular deque is full or not. */ + public boolean isFull() { + return right == arr.length; + } +} + +/** + * Your MyCircularDeque object will be instantiated and called as such: + * MyCircularDeque obj = new MyCircularDeque(k); + * boolean param_1 = obj.insertFront(value); + * boolean param_2 = obj.insertLast(value); + * boolean param_3 = obj.deleteFront(); + * boolean param_4 = obj.deleteLast(); + * int param_5 = obj.getFront(); + * int param_6 = obj.getRear(); + * boolean param_7 = obj.isEmpty(); + * boolean param_8 = obj.isFull(); + */ +//leetcode submit region end(Prohibit modification and deletion) + +} \ No newline at end of file diff --git a/Week01/NOTE.md b/Week01/NOTE.md index 50de30414..19c87bdbf 100644 --- a/Week01/NOTE.md +++ b/Week01/NOTE.md @@ -1 +1,40 @@ -学习笔记 \ No newline at end of file +学习笔记:java + +### 第一周: + +#### 一,数组、链表、跳表 + +​ 1,数组创建时在内存中连续,长度固定,查询快——根据下标查找时间复杂度O(1),遍历也快——CPU吞吐量。相对的增删慢——时间复杂度O(n)。 + +​ 2,链表创建时,无需在内存中申请连续的空间,增删快——时间复杂度O(1),查询慢——时间复杂度O(n). + +​ 3, 为了同时拥较低时间复杂度的增删和查询,——跳表,基于有序链表升维(类同数据库的索引),查询和增删时间复杂度都为O(logn)。 + +| | 随机查找时间复杂度 | 增删时间复杂度 | +| ---- | ------------------ | -------------- | +| 数组 | O(1) | O(n) | +| 链表 | O(n) | O(1) | +| 跳表 | O(logn) | O(logn) | + + + +#### 二,栈、队列、优先队列、双端队列 + +​ 1,栈,底层基于数组实现,先进后出,增删时间复杂度O(1),查找时间复杂度O(n). + +​ 2,队列,底层基于数组实现,先进先出,增删时间复杂度O(1),查找时间复杂度O(n). + +​ 3,优先队列,可以看做是一个堆,插入是O(1),取出是O(n)。 + +​ 4,双端队列,头尾都能进出,增删时间复杂度O(1),查找时间复杂度O(n). + + + +#### 三,算法题总结 + +##### 1,数组 + +​ 减少时间复杂度,排序,双指针夹逼的方法, + +​ 栈、队列都是基于数组实现的,所以用栈、队列解决的问题,都可以用数组解决,然后数组基本都是使用双指针来减少时间复杂度。 + diff --git a/Week01/ReverseLinkedList.java b/Week01/ReverseLinkedList.java new file mode 100644 index 000000000..337ac985a --- /dev/null +++ b/Week01/ReverseLinkedList.java @@ -0,0 +1,45 @@ +//反转一个单链表。 +// +// 示例: +// +// 输入: 1->2->3->4->5->NULL +//输出: 5->4->3->2->1->NULL +// +// 进阶: +//你可以迭代或递归地反转链表。你能否用两种方法解决这道题? +// Related Topics 链表 + +package com.cute.leetcode.editor.cn; +public class ReverseLinkedList { + public static void main(String[] args) { + Solution solution = new ReverseLinkedList().new Solution(); + } + //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 Solution { + public ListNode reverseList(ListNode head) { + ListNode newNode = null; + ListNode oldNode = head; + while (oldNode != null) { + //保存原链表的next + ListNode temp = oldNode.next; + //修改 next 指向 + oldNode.next = newNode; + //修改newNode + newNode = oldNode; + //修改oldNode指向下一个节点 + oldNode = temp; + } + return newNode; + } +} +//leetcode submit region end(Prohibit modification and deletion) + +} \ No newline at end of file diff --git a/Week01/ThreeSum.java b/Week01/ThreeSum.java new file mode 100644 index 000000000..553ca2f28 --- /dev/null +++ b/Week01/ThreeSum.java @@ -0,0 +1,67 @@ +//给你一个包含 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 数组 双指针 + +package com.cute.leetcode.editor.cn; + +import sun.security.jca.ProviderList; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ThreeSum { + public static void main(String[] args) { + Solution solution = new ThreeSum().new Solution(); + } + //leetcode submit region begin(Prohibit modification and deletion) +class Solution { + public List> threeSum(int[] nums) { + List> list = new ArrayList>(); + if (nums == null || nums.length <= 2) { + return list; + } + Arrays.sort(nums); + for (int k = 0; k < nums.length-2; k++) { + if (nums[k] > 0) { + break; + } + if (k > 0 && nums[k-1] == nums[k]) { + continue; + } + int left = k + 1; + int right = nums.length - 1; + while (left < right) { + int sum = nums[k] + nums[left] + nums[right]; + if (sum < 0) { + while (left < right && nums[left] == nums[++left]); + }else if (sum > 0) { + while (left < right && nums[right] == nums[--right]); + }else { + list.add(new ArrayList(Arrays.asList(nums[k], nums[left], nums[right]))); + while (left < right && nums[left] == nums[++left]); + while (left < right && nums[right] == nums[--right]); + } + } + } + return list; + } +} +//leetcode submit region end(Prohibit modification and deletion) + +} \ No newline at end of file diff --git a/Week01/TrappingRainWater.java b/Week01/TrappingRainWater.java new file mode 100644 index 000000000..000470745 --- /dev/null +++ b/Week01/TrappingRainWater.java @@ -0,0 +1,43 @@ +//给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 +// +// +// +// 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Mar +//cos 贡献此图。 +// +// 示例: +// +// 输入: [0,1,0,2,1,0,1,3,2,1,2,1] +//输出: 6 +// Related Topics 栈 数组 双指针 + +package com.cute.leetcode.editor.cn; + +import java.util.Stack; + +public class TrappingRainWater { + public static void main(String[] args) { + Solution solution = new TrappingRainWater().new Solution(); + } + //leetcode submit region begin(Prohibit modification and deletion) +class Solution { + public int trap(int[] height) { + Stack stack = new Stack<>(); + int sum = 0; + for (int i = 0; i < height.length; i++) { + while (!stack.empty() && height[i] > height[stack.peek()]) { + int top = stack.pop(); + if (stack.empty()) break; + int wide = i - stack.peek() - 1; + int boundH = Math.min(height[i], height[stack.peek()]) - height[top]; + sum += wide * boundH; + } + //递减入栈,相等也入栈 + stack.push(i); + } + return sum; + } +} +//leetcode submit region end(Prohibit modification and deletion) + +} \ No newline at end of file From eca3be0f7b92cf97343fbc1d0a5de5be91aca48e Mon Sep 17 00:00:00 2001 From: unknown <363595819@qq.com> Date: Sun, 21 Jun 2020 22:01:14 +0800 Subject: [PATCH 2/5] week02 --- Week02/GroupAnagrams.java | 52 +++++++++++++++++++ Week02/NOTE.md | 102 +++++++++++++++++++++++++++++++++++++- Week02/ValidAnagram.java | 44 ++++++++++++++++ Week02/ValidAnagram1.java | 50 +++++++++++++++++++ 4 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 Week02/GroupAnagrams.java create mode 100644 Week02/ValidAnagram.java create mode 100644 Week02/ValidAnagram1.java diff --git a/Week02/GroupAnagrams.java b/Week02/GroupAnagrams.java new file mode 100644 index 000000000..2efcf96e4 --- /dev/null +++ b/Week02/GroupAnagrams.java @@ -0,0 +1,52 @@ +//给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。 +// +// 示例: +// +// 输入: ["eat", "tea", "tan", "ate", "nat", "bat"] +//输出: +//[ +// ["ate","eat","tea"], +// ["nat","tan"], +// ["bat"] +//] +// +// 说明: +// +// +// 所有输入均为小写字母。 +// 不考虑答案输出的顺序。 +// +// Related Topics 哈希表 字符串 + +package com.cute.leetcode.editor.cn; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class GroupAnagrams { + public static void main(String[] args) { + Solution solution = new GroupAnagrams().new Solution(); + } + //leetcode submit region begin(Prohibit modification and deletion) +class Solution { + public List> groupAnagrams(String[] strs) { + if (strs == null || strs.length == 0) { + return new ArrayList<>(); + } + Map maps = new HashMap(); + for (int i = 0; i < strs.length; i++) { + char[] chs = strs[i].toCharArray(); + Arrays.sort(chs); + String key = String.valueOf(chs); + if (!maps.containsKey(key)) { + maps.put(key, new ArrayList<>()); + } + maps.get(key).add(strs[i]); + } + return new ArrayList(maps.values()); + } +} +//leetcode submit region end(Prohibit modification and deletion) + +} \ No newline at end of file diff --git a/Week02/NOTE.md b/Week02/NOTE.md index 50de30414..39e6bc831 100644 --- a/Week02/NOTE.md +++ b/Week02/NOTE.md @@ -1 +1,101 @@ -学习笔记 \ No newline at end of file +学习笔记 + +#### 一,关于 HashMap 的put、get: + +1,get + +```java +final Node getNode(int hash, Object key) { + Node[] tab; Node first, e; int n; K k; + //hash表table不为空,length>0, + if ((tab = table) != null && (n = tab.length) > 0 && + //hash & length-1 定位数组下标 + //HashMap的初始大小和扩容都是以2的次方来进行的,换句话说length-1换成二进制永远是全部为1,比如容量为16,则length-1为1111, + //感觉不到这个 & 运算的意义。。。。。 + (first = tab[(n - 1) & hash]) != null) { + + if (first.hash == hash && // always check first node + ((k = first.key) == key || (key != null && key.equals(k)))) + return first; + if ((e = first.next) != null) { + if (first instanceof TreeNode) //如果是红黑树 + return ((TreeNode)first).getTreeNode(hash, key); + do { + //hash相同,且key相等 + if (e.hash == hash && + ((k = e.key) == key || (key != null && key.equals(k)))) + return e; + } while ((e = e.next) != null); + } + } + return null; +} +``` + +2,put + +```java +final V putVal(int hash, K key, V value, boolean onlyIfAbsent, + boolean evict) { + //这个tab就是成员变量里的table + Node[] tab; + //这个就是数组上的链表,当桶上的对象太多的时候 就会转换成红黑树 + Node p; + int n, i; + // 如果tab数组未被初始化,初始化该数组 + if ((tab = table) == null || (n = tab.length) == 0) + n = (tab = resize()).length; + // 如果key没有存在过直接放到tab数组中 + if ((p = tab[i = (n - 1) & hash]) == null) + tab[i] = newNode(hash, key, value, null); + else { + //新的链表,需要放进来的元素 + Node e; + K k; + //如果put的key和hash恰好与对应桶的首个对象一样,那么可以不用考虑直接替换 + if (p.hash == hash && + ((k = p.key) == key || (key != null && key.equals(k)))) + e = p; + //第一个节点是红黑树TreeNode,即tree-bin + else if (p instanceof TreeNode) + e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value); + else { + //不是TreeNode,即为链表,遍历链表 + for (int binCount = 0; ; ++binCount) { + /** + 到达链表的尾端也没有找到key值相同的节点 + *则生成一个新的Node,并且判断链表的节点个数是不是到达转换成红黑树的上界 + *达到,则转换成红黑树 + */ + if ((e = p.next) == null) { + p.next = newNode(hash, key, value, null); + if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st + treeifyBin(tab, hash); + break; + } + if (e.hash == hash && + ((k = e.key) == key || (key != null && key.equals(k)))) + break; + //下一个节点 + p = e; + } + } + if (e != null) { // existing mapping for key + V oldValue = e.value; + if (!onlyIfAbsent || oldValue == null) + e.value = value; + afterNodeAccess(e); + return oldValue; + } + } + ++modCount; + //链表元素增加,并判断是否大于阈值,如果大于,则扩容 + if (++size > threshold) + resize(); + afterNodeInsertion(evict); + return null; +} +``` + + + diff --git a/Week02/ValidAnagram.java b/Week02/ValidAnagram.java new file mode 100644 index 000000000..089bb1c74 --- /dev/null +++ b/Week02/ValidAnagram.java @@ -0,0 +1,44 @@ +//给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 +// +// 示例 1: +// +// 输入: s = "anagram", t = "nagaram" +//输出: true +// +// +// 示例 2: +// +// 输入: s = "rat", t = "car" +//输出: false +// +// 说明: +//你可以假设字符串只包含小写字母。 +// +// 进阶: +//如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况? +// Related Topics 排序 哈希表 + +package com.cute.leetcode.editor.cn; + +import java.util.Arrays; + +public class ValidAnagram { + public static void main(String[] args) { + Solution solution = new ValidAnagram().new Solution(); + } + //leetcode submit region begin(Prohibit modification and deletion) +class Solution { + public boolean isAnagram(String s, String t) { + if (null == s || null == t || s.length() != t.length()) { + return false; + } + char[] sCh = s.toCharArray(); + char[] tCh = t.toCharArray(); + Arrays.sort(sCh); + Arrays.sort(tCh); + return Arrays.equals(sCh, tCh); + } +} +//leetcode submit region end(Prohibit modification and deletion) + +} \ No newline at end of file diff --git a/Week02/ValidAnagram1.java b/Week02/ValidAnagram1.java new file mode 100644 index 000000000..54a2030a3 --- /dev/null +++ b/Week02/ValidAnagram1.java @@ -0,0 +1,50 @@ +//给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 +// +// 示例 1: +// +// 输入: s = "anagram", t = "nagaram" +//输出: true +// +// +// 示例 2: +// +// 输入: s = "rat", t = "car" +//输出: false +// +// 说明: +//你可以假设字符串只包含小写字母。 +// +// 进阶: +//如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况? +// Related Topics 排序 哈希表 + +package com.cute.leetcode.editor.cn; + +import java.util.Arrays; + +public class ValidAnagram { + public static void main(String[] args) { + Solution solution = new ValidAnagram().new Solution(); + } + //leetcode submit region begin(Prohibit modification and deletion) +class Solution { + public boolean isAnagram(String s, String t) { + if (null == s || null == t || s.length() != t.length()) { + return false; + } + int[] table = new int[26]; + for (int i = 0; i < s.length(); i++) { + table[s.charAt(i) - 'a']++; + } + for (int i = 0; i < t.length(); i++) { + table[t.charAt(i) - 'a']--; + if (table[t.charAt(i) - 'a'] < 0) { + return false; + } + } + return true; + } +} +//leetcode submit region end(Prohibit modification and deletion) + +} \ No newline at end of file From 24a074fbffb3c5aa58d5dcbb94288ecaccbeb3d7 Mon Sep 17 00:00:00 2001 From: unknown <363595819@qq.com> Date: Sun, 5 Jul 2020 23:48:06 +0800 Subject: [PATCH 3/5] week03 commit by LuMan 20200705 --- ...ryTreeFromPreorderAndInorderTraversal.java | 79 +++++++++++++++++ Week03/LowestCommonAncestorOfABinaryTree.java | 88 +++++++++++++++++++ Week03/NOTE.md | 14 ++- 3 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 Week03/ConstructBinaryTreeFromPreorderAndInorderTraversal.java create mode 100644 Week03/LowestCommonAncestorOfABinaryTree.java diff --git a/Week03/ConstructBinaryTreeFromPreorderAndInorderTraversal.java b/Week03/ConstructBinaryTreeFromPreorderAndInorderTraversal.java new file mode 100644 index 000000000..41f8fa417 --- /dev/null +++ b/Week03/ConstructBinaryTreeFromPreorderAndInorderTraversal.java @@ -0,0 +1,79 @@ +//根据一棵树的前序遍历与中序遍历构造二叉树。 +// +// 注意: +//你可以假设树中没有重复的元素。 +// +// 例如,给出 +// +// 前序遍历 preorder = [3,9,20,15,7] +//中序遍历 inorder = [9,3,15,20,7] +// +// 返回如下的二叉树: +// +// 3 +// / \ +// 9 20 +// / \ +// 15 7 +// Related Topics 树 深度优先搜索 数组 + +package com.cute.leetcode.editor.cn; + +import javax.swing.tree.TreeNode; +import java.util.HashMap; + +public class ConstructBinaryTreeFromPreorderAndInorderTraversal { + public static void main(String[] args) { + Solution solution = new ConstructBinaryTreeFromPreorderAndInorderTraversal().new Solution(); + } + //leetcode submit region begin(Prohibit modification and deletion) +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + private Map map; + public TreeNode buildTree(int[] preorder, int[] inorder) { + int n = preorder.length; + map = new HashMap<>(); + for (int i = 0; i < n; i++) { + map.put(inorder[i], i); + } + return dep(preorder, 0, n - 1, + inorder, 0, n - 1); + } + + private TreeNode dep(int[] preorder, int preLeftIndex, int preRightInd, + int[] inorder, int inoLeftIndex, int inoRightIndex) { + //终结条件 + if (preLeftIndex > preRightInd) { + return null; + } + //中序遍历的根节点就是第一个 + int preRoot = preLeftIndex; + //取出根节点在前序遍历中的位置 + int inoRoot = map.get(preorder[preRoot]); + + //建立根节点 + TreeNode root = new TreeNode(preorder[preRoot]); + + //左子树中的节点数目 + int sizeLeft = inoRoot - inoLeftIndex; + + //递归构造左子树 + root.left = dep(preorder, preLeftIndex + 1, preLeftIndex + sizeLeft, + inorder, inoLeftIndex, inoRoot - 1); + //递归构造右子树 + root.right = dep(preorder, preLeftIndex + sizeLeft + 1, preRightInd, + inorder, inoRoot + 1, inoRightIndex); + return root; + } +} +//leetcode submit region end(Prohibit modification and deletion) + +} \ No newline at end of file diff --git a/Week03/LowestCommonAncestorOfABinaryTree.java b/Week03/LowestCommonAncestorOfABinaryTree.java new file mode 100644 index 000000000..81d174db3 --- /dev/null +++ b/Week03/LowestCommonAncestorOfABinaryTree.java @@ -0,0 +1,88 @@ +//给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 +// +// 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大( +//一个节点也可以是它自己的祖先)。” +// +// 例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4] +// +// +// +// +// +// 示例 1: +// +// 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 +//输出: 3 +//解释: 节点 5 和节点 1 的最近公共祖先是节点 3。 +// +// +// 示例 2: +// +// 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 +//输出: 5 +//解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。 +// +// +// +// +// 说明: +// +// +// 所有节点的值都是唯一的。 +// p、q 为不同节点且均存在于给定的二叉树中。 +// +// Related Topics 树 + +package com.cute.leetcode.editor.cn; + +import javax.swing.tree.TreeNode; + +public class LowestCommonAncestorOfABinaryTree { + public static void main(String[] args) { + Solution solution = new LowestCommonAncestorOfABinaryTree().new Solution(); + } + //leetcode submit region begin(Prohibit modification and deletion) +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +class Solution { + private TreeNode ans; + public Solution() { + this.ans = null; + } + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + this.dep(root, p, q); + return this.ans; + } + private boolean dep(TreeNode root, TreeNode p, TreeNode q) { + //结束条件 + if (root == null) { + return false; + } + //递归 + boolean leftSon = dep(root.left, p, q); + //如果左支上已找到公共祖先,结束 + if (this.ans != null) { + return false; + } + boolean rightSon = dep(root.right, p, q); + + //本层逻辑 + if ((leftSon && rightSon) || + (root.val == q.val || root.val == p.val) && (leftSon || rightSon)) { + ans = root; + } + return leftSon || rightSon || (root.val == q.val) || (root.val == p.val); + } +} + +//leetcode submit region end(Prohibit modification and deletion) + +} \ No newline at end of file diff --git a/Week03/NOTE.md b/Week03/NOTE.md index 50de30414..fb8995f14 100644 --- a/Week03/NOTE.md +++ b/Week03/NOTE.md @@ -1 +1,13 @@ -学习笔记 \ No newline at end of file +学习笔记 + +### 一、递归 + +递归一般具有的要素: + +1、递归终止条件 + +2、处理当前逻辑 + +3、递归到下一层 + +4、清理当前层,如果需要 \ No newline at end of file From 553915a80356d19cf0828c8feae97152b9b20d35 Mon Sep 17 00:00:00 2001 From: unknown <363595819@qq.com> Date: Sun, 5 Jul 2020 23:49:33 +0800 Subject: [PATCH 4/5] week04 commit by LuMan 20200705 --- Week04/JumpGame.java | 42 +++++++++++++++++ Week04/LemonadeChange.java | 91 +++++++++++++++++++++++++++++++++++++ Week04/NOTE.md | 14 +++++- Week04/NumberOfIslands.java | 73 +++++++++++++++++++++++++++++ Week04/SearchA2dMatrix.java | 68 +++++++++++++++++++++++++++ 5 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 Week04/JumpGame.java create mode 100644 Week04/LemonadeChange.java create mode 100644 Week04/NumberOfIslands.java create mode 100644 Week04/SearchA2dMatrix.java diff --git a/Week04/JumpGame.java b/Week04/JumpGame.java new file mode 100644 index 000000000..35ff05f48 --- /dev/null +++ b/Week04/JumpGame.java @@ -0,0 +1,42 @@ +//给定一个非负整数数组,你最初位于数组的第一个位置。 +// +// 数组中的每个元素代表你在该位置可以跳跃的最大长度。 +// +// 判断你是否能够到达最后一个位置。 +// +// 示例 1: +// +// 输入: [2,3,1,1,4] +//输出: true +//解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。 +// +// +// 示例 2: +// +// 输入: [3,2,1,0,4] +//输出: false +//解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。 +// +// Related Topics 贪心算法 数组 + +package com.cute.leetcode.editor.cn; +public class JumpGame { + public static void main(String[] args) { + Solution solution = new JumpGame().new Solution(); + } + //leetcode submit region begin(Prohibit modification and deletion) +class Solution { + public boolean canJump(int[] nums) { + int n = nums.length; + int rightIndex = n - 1; + for (int i = n - 1; i >= 0; i--) { + if (i + nums[i] >= rightIndex) { + rightIndex = i; + } + } + return rightIndex == 0; + } +} +//leetcode submit region end(Prohibit modification and deletion) + +} \ No newline at end of file diff --git a/Week04/LemonadeChange.java b/Week04/LemonadeChange.java new file mode 100644 index 000000000..4aefc21d4 --- /dev/null +++ b/Week04/LemonadeChange.java @@ -0,0 +1,91 @@ +//在柠檬水摊上,每一杯柠檬水的售价为 5 美元。 +// +// 顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。 +// +// 每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。 +// +// 注意,一开始你手头没有任何零钱。 +// +// 如果你能给每位顾客正确找零,返回 true ,否则返回 false 。 +// +// 示例 1: +// +// 输入:[5,5,5,10,20] +//输出:true +//解释: +//前 3 位顾客那里,我们按顺序收取 3 张 5 美元的钞票。 +//第 4 位顾客那里,我们收取一张 10 美元的钞票,并返还 5 美元。 +//第 5 位顾客那里,我们找还一张 10 美元的钞票和一张 5 美元的钞票。 +//由于所有客户都得到了正确的找零,所以我们输出 true。 +// +// +// 示例 2: +// +// 输入:[5,5,10] +//输出:true +// +// +// 示例 3: +// +// 输入:[10,10] +//输出:false +// +// +// 示例 4: +// +// 输入:[5,5,10,10,20] +//输出:false +//解释: +//前 2 位顾客那里,我们按顺序收取 2 张 5 美元的钞票。 +//对于接下来的 2 位顾客,我们收取一张 10 美元的钞票,然后返还 5 美元。 +//对于最后一位顾客,我们无法退回 15 美元,因为我们现在只有两张 10 美元的钞票。 +//由于不是每位顾客都得到了正确的找零,所以答案是 false。 +// +// +// +// +// 提示: +// +// +// 0 <= bills.length <= 10000 +// bills[i] 不是 5 就是 10 或是 20 +// +// Related Topics 贪心算法 + +package com.cute.leetcode.editor.cn; +public class LemonadeChange { + public static void main(String[] args) { + Solution solution = new LemonadeChange().new Solution(); + } + //leetcode submit region begin(Prohibit modification and deletion) +class Solution { + public boolean lemonadeChange(int[] bills) { + int fiveCount = 0; + int tenCount = 0; + for (int bill: bills) { + if (bill == 5) { + fiveCount++; + }else if (bill == 10) { + if (fiveCount == 0) { + return false; + }else { + fiveCount--; + tenCount++; + } + }else { + if (fiveCount > 0 && tenCount > 0) { + fiveCount--; + tenCount--; + }else if (fiveCount >= 3) { + fiveCount -=3; + }else { + return false; + } + } + } + return true; + } +} +//leetcode submit region end(Prohibit modification and deletion) + +} \ No newline at end of file diff --git a/Week04/NOTE.md b/Week04/NOTE.md index 50de30414..ea33af639 100644 --- a/Week04/NOTE.md +++ b/Week04/NOTE.md @@ -1 +1,13 @@ -学习笔记 \ No newline at end of file +学习笔记 + +##### 一、递归,深度优先,广度优先 + +深度优先,类似于二叉搜索树的中序遍历,先往下一层、再本层逻辑 + +广度优先,需要先将下一层的子序放入队列保存 + +##### 二、贪心算法 + +##### 三、二分法查找 + +结合数组遍历的双指针夹逼方法 \ No newline at end of file diff --git a/Week04/NumberOfIslands.java b/Week04/NumberOfIslands.java new file mode 100644 index 000000000..19703b70a --- /dev/null +++ b/Week04/NumberOfIslands.java @@ -0,0 +1,73 @@ +//给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。 +// +// 岛屿总是被水包围,并且每座岛屿只能由水平方向或竖直方向上相邻的陆地连接形成。 +// +// 此外,你可以假设该网格的四条边均被水包围。 +// +// +// +// 示例 1: +// +// 输入: +//[ +//['1','1','1','1','0'], +//['1','1','0','1','0'], +//['1','1','0','0','0'], +//['0','0','0','0','0'] +//] +//输出: 1 +// +// +// 示例 2: +// +// 输入: +//[ +//['1','1','0','0','0'], +//['1','1','0','0','0'], +//['0','0','1','0','0'], +//['0','0','0','1','1'] +//] +//输出: 3 +//解释: 每座岛屿只能由水平和/或竖直方向上相邻的陆地连接而成。 +// +// Related Topics 深度优先搜索 广度优先搜索 并查集 + +package com.cute.leetcode.editor.cn; +public class NumberOfIslands { + public static void main(String[] args) { + Solution solution = new NumberOfIslands().new Solution(); + } + //leetcode submit region begin(Prohibit modification and deletion) +class Solution { + public int numIslands(char[][] grid) { + if (grid == null || grid.length == 0) { + return 0; + } + int num = 0; + int k = grid.length; + int h = grid[0].length; + for (int i = 0; i < k; i++) { + for (int j = 0; j < h; j++) { + if (grid[i][j] == '1') { + num++; + dfs(grid, i, j, k, h); + } + } + } + return num; + } + + private void dfs(char[][] grid, int i, int j, int k, int h) { + if (i < 0 || j < 0 || i >= k || j >= h || grid[i][j] == '0' ) { + return ; + } + grid[i][j] = '0'; + dfs(grid, i-1, j, k, h); + dfs(grid, i+1, j, k, h); + dfs(grid, i, j-1, k, h); + dfs(grid, i, j+1, k, h); + } +} +//leetcode submit region end(Prohibit modification and deletion) + +} \ No newline at end of file diff --git a/Week04/SearchA2dMatrix.java b/Week04/SearchA2dMatrix.java new file mode 100644 index 000000000..4b65f013e --- /dev/null +++ b/Week04/SearchA2dMatrix.java @@ -0,0 +1,68 @@ +//编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性: +// +// +// 每行中的整数从左到右按升序排列。 +// 每行的第一个整数大于前一行的最后一个整数。 +// +// +// 示例 1: +// +// 输入: +//matrix = [ +// [1, 3, 5, 7], +// [10, 11, 16, 20], +// [23, 30, 34, 50] +//] +//target = 3 +//输出: true +// +// +// 示例 2: +// +// 输入: +//matrix = [ +// [1, 3, 5, 7], +// [10, 11, 16, 20], +// [23, 30, 34, 50] +//] +//target = 13 +//输出: false +// Related Topics 数组 二分查找 + +package com.cute.leetcode.editor.cn; +public class SearchA2dMatrix { + public static void main(String[] args) { + Solution solution = new SearchA2dMatrix().new Solution(); + } + //leetcode submit region begin(Prohibit modification and deletion) +class Solution { + public boolean searchMatrix(int[][] matrix, int target) { + int m; + if (null == matrix || (m = matrix.length) == 0) { + return false; + } + int n = matrix[0].length; + + int left = 0; + int right = m * n - 1; + + int midIndex; + int midValue; + while (left <= right) { + midIndex = (left + right) / 2; + midValue = matrix[midIndex / n][midIndex % n]; + if (midValue == target) { + return true; + } + if (midValue > target) { + right = midIndex - 1; + }else { + left = midIndex + 1; + } + } + return false; + } +} +//leetcode submit region end(Prohibit modification and deletion) + +} \ No newline at end of file From 12a5788171c651c75d209deaae4808cc35d54eb7 Mon Sep 17 00:00:00 2001 From: unknown <363595819@qq.com> Date: Mon, 6 Jul 2020 00:26:49 +0800 Subject: [PATCH 5/5] week04 commit by Lu --- Week04/JumpGameIi.java | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 Week04/JumpGameIi.java diff --git a/Week04/JumpGameIi.java b/Week04/JumpGameIi.java new file mode 100644 index 000000000..8557f1ddd --- /dev/null +++ b/Week04/JumpGameIi.java @@ -0,0 +1,44 @@ +//给定一个非负整数数组,你最初位于数组的第一个位置。 +// +// 数组中的每个元素代表你在该位置可以跳跃的最大长度。 +// +// 你的目标是使用最少的跳跃次数到达数组的最后一个位置。 +// +// 示例: +// +// 输入: [2,3,1,1,4] +//输出: 2 +//解释: 跳到最后一个位置的最小跳跃数是 2。 +//  从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。 +// +// +// 说明: +// +// 假设你总是可以到达数组的最后一个位置。 +// Related Topics 贪心算法 数组 + +package com.cute.leetcode.editor.cn; +public class JumpGameIi { + public static void main(String[] args) { + Solution solution = new JumpGameIi().new Solution(); + } + //leetcode submit region begin(Prohibit modification and deletion) +class Solution { + public int jump(int[] nums) { + int m = nums.length; + int end = 0; + int postIndex = 0; + int steps = 0; + for (int i = 0; i < m - 1; i++) { + postIndex = Math.max(postIndex, i + nums[i]); + if (i == end) {//end用于记每一步 步长,从当前i到PostIndex + end = postIndex; + steps++; + } + } + return steps; + } +} +//leetcode submit region end(Prohibit modification and deletion) + +} \ No newline at end of file