面试题-合并list/判断是否是有效IP地址/查找二叉搜索树的第二小节点

问题1,合并两个list

问题描述

给定两个list集合,集合存放无序、重复的整数,求并集

输入描述:
输入两个整数list

输出描述:
输出他们的并集

示例

示例1

输入
4,2,1
1,2,3
输出
1,2,3,4

解决思路

分析

需要明确list中包含重复的元素,而且是无序的。

方法

  1. 通过java list自带的方法解决,时间复杂度无法自控
  2. 通过两个下标指针的移动解决

代码实现

// 思路1实现
public class Main{
    public List<Integer> merge (List<Integer> a, List<Integer> b) {
	    List<Integer> result = new ArrayList<>(a.size()+ b.size());
	
	    result.addAll(a);
	    result.removeAll(b);
	    result.addAll(b);
	
	    return result;
	}
}
// 思路2实现
public class Main {
   public List<Integer> merge (List<Integer> a, List<Integer> b) {

        // sort方法本身用到arrays.sort方法
        a.sort(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                if (o1 > o2) {
                    return 1;
                }
                return -1;
            }
        });

        b.sort(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                if (o1 > o2) {
                    return 1;
                }
                return -1;
            }
        });

        List<Integer> result = new ArrayList<>(a.size()+ b.size());
        if (a.size() > b.size()) {
            List<Integer> temp = a;
            a = b;
            b = temp;
        }

        int i = 0;
        int j = 0;
        while (i < a.size() && j < b.size()) {
            if (a.get(i).equals(b.get(j))) {
                if (i >= 1 && !a.get(i).equals(a.get(i - 1)) ) {
                    result.add(a.get(i));
                }
                i++;
                j++;
                continue;
            }

            while (a.get(i) < b.get(j) && i < a.size()) {
                result.add(a.get(i));
                i++;
                continue;
            }

            while (a.get(i) > b.get(j) && j < b.size()) {
                result.add(b.get(j));
                j++;
                continue;
            }
        }

        while (j < b.size()) {
            result.add(b.get(j));
            j++;
            continue;
        }

        return result;
    }
}

问题2,校验IP地址

问题描述

输入一个IP地址的字符数组,判断这个IP地址是否有效

输入描述:
输入一个IP地址的字符数组

输出描述:
输出是否是有效IP

示例

示例1

输入
10.255.1.1
输出
true

解决思路

分析

分析校验的内容:

  1. 判断‘.’的个数是否正确
  2. 判断每一段的范围是否是[0,255]

方法

  1. 通过自定义实现字符数组转int来实现判断每一段的数字范围

代码实现

public class IP地址校验 {
    // 校验内容
    // ip有四个段,也就是说有三个.
    // 每个段的范围 0 - 255
    public boolean isIP (char[] arr) {
        int strat = 0;
        int end = 0;
        int count = 0;
        for (int i = 0; i < arr.length; i++) {

            if (arr[i] >= '0' && arr[i] <= '9') {
                end++;
                continue;
            }

            if (arr[i] >= '.' && pareInt(arr, strat, end) <= 255) {
                strat = i + 1;
                end = strat;
                count++;
                continue;
            }

            return false;
        }

        if (count != 3) {
            return false;
        }

        return true;
    }

    private int pareInt (char[] arr, int start, int end) {
        int result = 0;
        int temp = 1;
        for (int i = end - 1; i >= start; i--) {
            result += (arr[i] - '0') * temp;
            temp *= 10;
        }

        return result;
    }
}

问题3,查找二叉搜索树的第二小节点

问题描述

输入是一棵二叉搜索树的跟节点,输出第二小节点的值或节点(要求:不能使用额外的空间)

输入描述:
输入一个二叉搜索树的跟节点

输出描述:
输出第二小节点的值或节点

示例

示例1

输入 (这里直接展示了树的图片,实际输入是跟节点)
在这里插入图片描述

输出
3

解决思路

分析

分析第二小节点的情况,这里的第二小只能存在两种情况:

  1. 第二小节点是根节点,说明最小的节点是此跟节点的左节点
  2. 第二小节点是左节点,说明这个左节点位于某个根节点的右子树上,这样最小的节点即为该跟节点

方法

  1. 在不申请任何额外空间的情况下查找
  2. 使用额外的空间,来自力扣的230题(下文有地址)1

代码实现

// 方法一
// PS:博主没有经过严格的复测,代码有问题,请指出
public class 二叉搜索 {

    public TreeNode getSecond (TreeNode root) {
        TreeNode temp = root;
        TreeNode parNode = root;
        int min = root.val;
        while (temp != null) {
            min = Math.min(min, temp.val);
            // 左右子树都包含的情况
            if (temp.left == null && temp.right == null) {
                if (temp.val == parNode.val) {
                    return null;
                }

                // 区分第二小的节点是跟节点,还是左节点的情况
                // 左节点:左节点的值<他的父节点的值;左节点的值>最小值
                if (temp.val < parNode.val && temp.val > min) {
                    return temp;
                } else {
                    return parNode;
                }
            }

			// 如果碰到了节点的左子树为空,继续查找他的右子树,此时的根节点的值是最小值
            if (temp.left == null && temp.right != null) {
                parNode = temp;
                temp = temp.right;
                continue;
            }

            parNode = temp;
            temp = temp.left;
        }

        return temp;
    }
}
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;
    }
}

// 力扣原题是:230. 二叉搜索树中第K小的元素,需要申请额外的空间
// 这里提供两种思路
// 1、利用中序遍历的特点,二叉搜索树的中序遍历,是有序的数组
// 2、利用队列实现迭代查找,避免第一种方法的全部遍历
public class 二叉搜索树第k小节点 {   
    // 1、通过二叉搜索树中序遍历的特点
    // 二叉搜索树,中序遍历后是一个有顺序的数组
    // 第k小的元素就是排好序数组的第k-1个元素
    public ArrayList<Integer> inorder(TreeNode root, ArrayList<Integer> arr) {
        if (root == null) {
            return arr;
        }

        inorder(root.left, arr);
        arr.add(root.val);
        inorder(root.right, arr);

        return arr;
    }

    public int getK(TreeNode root, int k) {
        ArrayList<Integer> arr = inorder(root, new ArrayList<>());
        return arr.get(k - 1);
    }

 	// 2、利用队列实现迭代,这样避免了检索所有的节点的情况
    public int kthSmallest(TreeNode root, int k) {
        LinkedList<TreeNode> queue = new LinkedList<TreeNode>();

        while (true) {
            // 依次放入左节点
            while (root != null) {
                queue.add(root);
                root = root.left;
            }
            // 取最后的节点,也就是当前列表中最小的节点,弹出
            root = queue.removeLast();
            // 第k小减减,判断是否符合k小的情况
            if (--k == 0) return root.val;
            // 如果节点有右节点,需要重新赋值右节点,依次放入,迭代
            root = root.right;
        }
    }
}

PS:如果不对请指出,不喜勿喷。


  1. 力扣230题地址:https://leetcode-cn.com/problems/kth-smallest-element-in-a-bst/ ↩︎

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值