diff --git a/Leecode/src/main/java/sort/ThreeSum.java b/Leecode/src/main/java/sort/ThreeSum.java new file mode 100644 index 0000000..4cd21ca --- /dev/null +++ b/Leecode/src/main/java/sort/ThreeSum.java @@ -0,0 +1,100 @@ +package sort; + +import com.sun.corba.se.impl.ior.FreezableList; + +import java.util.*; + +/** + * 三数之和 + * 给你一个包含 n 个整数的数组nums,判断nums中是否存在三个元素 a,b,c ,使得a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组 + *

+ * 思路: + * 「不重复」的本质是什么?我们保持三重循环的大框架不变,只需要保证: + * 第二重循环枚举到的元素不小于当前第一重循环枚举到的元素; + * 第三重循环枚举到的元素不小于当前第二重循环枚举到的元素。 + *

+ * 也就是说,我们枚举的三元组 (a, b, c) 满足 a≤b≤c,保证了只有 (a,b,c) 这个顺序会被枚举到,而 (b,a,c)、(c,b,a) 等等这些不会 + * 这样就减少了重复。要实现这一点,我们可以将数组中的元素从小到大进行排序,随后使用普通的三重循环就可以满足上面的要求。 + *

+ * 使用双指针让时间复杂度变为O(n^2) + */ +public class ThreeSum { + + public static void main(String[] args) { + + int[] nums = {-1, 0, 1, 2, -1, -4}; + + List> result = threeSum(nums); + + System.out.println(result); + + + } + + + public static List> threeSum(int[] nums) { + + List> parentList = new ArrayList<>(); + + if (nums.length < 3) { + return parentList; + } + //先排序 + Arrays.sort(nums); + + //后累加 + //第一个数的索引i + for (int i = 0; i < nums.length; i++) { + + if(nums[i]>0) break; + + //为了避免这一次和前一次重复 + if (i > 0 && nums[i] == nums[i - 1]) { + continue; + } + + //第三个数的索引k + int k = nums.length - 1; + + //所需要的第二个数和第三个数之和 + int need = -nums[i]; + + //第二个数的索引j + for (int j = i + 1; j < nums.length; j++) { + //为了避免这一次和前一次重复 + if (j > i + 1 && nums[j] == nums[j - 1]) { + continue; + } + + while (j < k && nums[j] + nums[k] > need) { + k--; + } + + //判断是通过什么条件出来的,如果是第一个条件,就证明这个j不合适,反之就合适,是需要的数 + if (j == k) { + //这里直接break而不是continue,因为如果这个数加上后面的数都大于need,那后面的循环没有必要了 + // 后面的循环一定比这次的还有大 + break; + } + //如果是第二个条件跳出的循环 + if (nums[j] + nums[k] == need) { + List list = new ArrayList<>(); + list.add(nums[i]); + list.add(nums[j]); + list.add(nums[k]); + parentList.add(list); + } + + + } + + + } + + + return parentList; + + } + + +} diff --git a/Leecode/src/main/java/tree/DeleteNode.java b/Leecode/src/main/java/tree/DeleteNode.java index 00c67fb..fef6b63 100644 --- a/Leecode/src/main/java/tree/DeleteNode.java +++ b/Leecode/src/main/java/tree/DeleteNode.java @@ -7,8 +7,9 @@ import java.util.List; import static tree.InorderTraversal.inorderTraversal1; - - +/** + * 删除二叉排序树的某个节点 + */ public class DeleteNode { public static void main(String[] args) { @@ -26,7 +27,7 @@ public class DeleteNode { TreeNode2.setRight(TreeNode5); TreeNode3.setLeft(TreeNode6); - deleteNode(root,5); + deleteNode(root, 5); List integers = inorderTraversal1(root); @@ -36,69 +37,65 @@ public class DeleteNode { } - public static void deleteNode(TreeNode root,int value){ + public static void deleteNode(TreeNode root, int value) { //删除的是有左右两个子树的节点 - TreeNode p =root; + TreeNode p = root; //记录当前节点的父节点 TreeNode pp = null; //寻找到要删除的节点和他的父节点 - while(p != null && p.val !=value){ - pp=p; - if(p.val < value){ - p=p.right; - }else if(p.val>value){ - p=p.left; + while (p != null && p.val != value) { + pp = p; + if (p.val < value) { + p = p.right; + } else if (p.val > value) { + p = p.left; } } //判断是根据那个条件出来的 - if(p == null){ + if (p == null) { System.out.println("未找到要删除的节点的值..."); return; - }else if(p.val == value){ + } else if (p.val == value) { //p是要删除的节点,pp是他的父节点,如果pp=null,删除的就是root //判断删除的节点有几个子树 - if (p.left !=null &&p.right !=null){ + if (p.left != null && p.right != null) { //左右子树都有,将找到右子树最小的节点,将他的值付给p,然后变成删除这个最小的数 - TreeNode min=p.right; + TreeNode min = p.right; //记录他的父节点 - TreeNode flag=p; - while (min.left !=null){ - flag=min; - min=min.left; + TreeNode flag = p; + while (min.left != null) { + flag = min; + min = min.left; } - p.val=min.val; - p=min; - pp=flag; + p.val = min.val; + p = min; + pp = flag; } //现在要删除的节点最多只有一个子树 - TreeNode child =null; - if(p.left !=null){ - child=p.left; - }else if (p.right !=null){ - child=p.right; + TreeNode child = null; + if (p.left != null) { + child = p.left; + } else if (p.right != null) { + child = p.right; } - if(pp ==null){ + if (pp == null) { //要删除的是根节点 - root=child; - }else if(pp.left == p)pp.left=child; - else pp.right=child; + root = child; + } else if (pp.left == p) pp.left = child; + else pp.right = child; } - - - + + } - - - } diff --git a/Leecode/src/main/java/tree/InorderTraversal.java b/Leecode/src/main/java/tree/InorderTraversal.java index 5785642..f3e5758 100644 --- a/Leecode/src/main/java/tree/InorderTraversal.java +++ b/Leecode/src/main/java/tree/InorderTraversal.java @@ -5,6 +5,9 @@ import lombok.Data; import java.util.ArrayList; import java.util.List; +/** + * 中序遍历二叉排序树 + */ public class InorderTraversal { public static void main(String[] args) {