This commit is contained in:
markilue 2022-05-24 18:43:41 +08:00
commit b3c7303820
3 changed files with 199 additions and 37 deletions

View File

@ -0,0 +1,162 @@
package sort;
import com.sun.corba.se.impl.ior.FreezableList;
import java.util.*;
/**
* 三数之和
* 给你一个包含 n 个整数的数组nums判断nums中是否存在三个元素 abc 使得a + b + c = 0 请你找出所有和为 0 且不重复的三元组
* <p>
* 思路
* 不重复的本质是什么我们保持三重循环的大框架不变只需要保证
* 第二重循环枚举到的元素不小于当前第一重循环枚举到的元素
* 第三重循环枚举到的元素不小于当前第二重循环枚举到的元素
* <p>
* 也就是说我们枚举的三元组 (a, b, c) 满足 abc保证了只有 (a,b,c) 这个顺序会被枚举到 (b,a,c)(c,b,a) 等等这些不会
* 这样就减少了重复要实现这一点我们可以将数组中的元素从小到大进行排序随后使用普通的三重循环就可以满足上面的要求
* <p>
* 使用双指针让时间复杂度变为O(n^2)
*/
public class ThreeSum {
public static void main(String[] args) {
int[] nums = {-1, 0, 1, 2, -1, -4};
List<List<Integer>> result = threeSum(nums);
System.out.println(result);
}
public static List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> 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<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[k]);
parentList.add(list);
}
}
}
return parentList;
}
//更简洁一点的思路
public static List<List<Integer>> threeSum1(int[] nums) {
List<List<Integer>> 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 j=i+1;
//开始遍历
while(j<k){
//三数之和
int sum = nums[i]+nums[j]+nums[k];
if(sum<0){
//不够了
j++;
}else if(sum>0){
//太多了
k--;
}else {
parentList.add(new ArrayList<Integer>(Arrays.asList(nums[i],nums[j],nums[k])));
//为了避免和上一次重复
while (j<k&&nums[j+1]==nums[j]){j++;} //相同中间数只能出现一次
while (j<k&&nums[k-1]==nums[k]){k--;} //相同最大数只能出现一次
j++;
k--;
}
}
}
return parentList;
}
}

View File

@ -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<Integer> 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;
}
}
}

View File

@ -5,6 +5,9 @@ import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 中序遍历二叉排序树
*/
public class InorderTraversal {
public static void main(String[] args) {