阿里笔试2023-3-15

太菜了,记录一下笔试题目,代码有更好解法欢迎分享。
1、满二叉子树的数量。
给定一颗二叉树,试求这课二叉树有多少个节点满足以该节点为根的子树是满二叉树?满二叉树指每一层都达到节点最大值。
第一行输入n表示节点数量,接下来n行第一个代表左儿子,第二个代表右儿子。

public class Main {

    static int res = 0;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[][] nums = new int[n][2];
        for (int i = 0; i < n; i ++) {
            nums[i][0] = in.nextInt();
            nums[i][1] = in.nextInt();
        }
        new Main().isFullTree(nums, 1)System.out.println(res);
    }

    public int height(int[][] nums, int root) {
        if (root == -1) {
            return 0;
        }
        return Math.max(height(nums, nums[root - 1][0]), height(nums, nums[root - 1][1])) + 1;
    }

    public boolean isFullTree(int[][] nums, int root) {
        if (root == -1) {
            return true;
        }
        if (isFullTree(nums, nums[root - 1][0]) && isFullTree(nums, nums[root - 1][1]) && height(nums, nums[root - 1][0]) == height(nums, nums[root - 1][1])) {
            res ++;
            return true;
        } else {
            return false;
        }
    }
}

上述解法时间复杂度O(n),空间复杂度o()
另外,可以掌握根据数组进行二叉树建树

class TreeNode {
    TreeNode left;
    TreeNode right;
    int val;
    public TreeNode() {}
    public TreeNode(int val) {
        this.val = val;
    }
    public TreeNode (TreeNode left, TreeNode right, int val) {
        this.left = left;
        this.right = right;
        this.val = val;
    }
}

public static void main(String[] args) {
    List<TreeNode> nodeList = new ArrayList<>();
    nodeList.add(null);
    for (int i = 1; i <= n; i ++) {
        nodeList.add(new TreeNode(i));
    }
    for (int i = 0; i < n; i ++) {
        if (nums[i][0] == -1) {
            nodeList.get(i + 1).left = null;
        } else {
            nodeList.get(i + 1).left = nodeList.get(nums[i][0]);
        }
        if (nums[i][1] == -1) {
            nodeList.get(i + 1).right = null;
        } else {
            nodeList.get(i + 1).right = nodeList.get(nums[i][1]);
        }
    }
}

2、三元组计数。
给定一个数组,计算有多少个三元组0<=i<j<k<n,且max(nums[i], nums[j], nums[k]) - min(nums[i], nums[j], nums[k]) = 1。
第一行输入n表示数组个数,第二行输入n个整数。

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    int n = scanner.nextInt();
    int[] nums = new int[n];
    for (int i = 0; i < n; i++) {
        nums[i] = scanner.nextInt();
    }
    Arrays.sort(nums);
    Map<Integer, Integer> map = new HashMap<>();
    int res = 0;
    for (int i = 0; i < n; i ++) {
        map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
    }
    for (int i = 0; i < n; i ++) {
        if (i > 0 && nums[i] == nums[i - 1]) {
            continue;
        }
        if (map.containsKey(nums[i] + 1)) {
            int low = map.get(nums[i]);
            int high = map.get(nums[i] + 1);
            if (low == 1 && high == 1) {
                continue;
            }
            if (high > 1) {
                res += low * high * (high - 1) / 2;
            }
            if (low > 1) {
                res += high * low * (low - 1) / 2;
            }
        }
    }
    System.out.println(res);
}

上述解法时间复杂度O(nlog(n)),空间复杂度O(n)。
3、乘2除2。
在n个元素的数组中选择k个元素,每个元素要么乘以2,要么除以2并向下取整,使得操作完后数组的极差尽可能小,并且输出极差。极差为最大值减去最小值。
第一行输入整数n和k。第二行输入n个整数表示数组。

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    int n = scanner.nextInt();
    int k = scanner.nextInt();
    int[] nums = new int[n];
    for (int i = 0; i < n; i++) {
        nums[i] = scanner.nextInt();
    }
    Comparator<Integer> comparator = new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o2 - o1;
        }
    };
    Arrays.sort(nums);
    PriorityQueue<Integer> queueMin = new PriorityQueue<>(comparator);
    PriorityQueue<Integer> queueMid = new PriorityQueue<>(comparator);
    PriorityQueue<Integer> queueMax = new PriorityQueue<>(comparator);
    int minMin = Integer.MAX_VALUE, midMin = Integer.MAX_VALUE, maxMin = Integer.MAX_VALUE;
    for (int i = 0; i < k ; i ++) {
        minMin = Math.min(minMin, 2 * nums[i]);
        queueMin.add(2 * nums[i]);
    }
    for (int i = k; i < n; i ++) {
        midMin = Math.min(midMin, nums[i]);
        queueMid.add(nums[i]);
    }
    int res = Integer.MAX_VALUE;
    if (k == 0) {
        res = Math.min(res, queueMid.peek() - midMin);
    } else {
        res = Math.min(res, Math.max(queueMin.peek(), queueMid.peek()) - Math.min(minMin, midMin));
    }
    for (int i = 0; i < k; i ++) {
        int tempMin = queueMin.poll();
        queueMid.add(tempMin / 2);
        midMin = Math.min(midMin, tempMin / 2);
        int tempMid = queueMid.poll();
        queueMax.add(tempMid / 2);
        maxMin = Math.min(maxMin, tempMid / 2);
        if (i == k - 1) {
            res = Math.min(res, Math.max(queueMid.peek(), queueMax.peek()) - Math.min(Math.min(minMin, midMin), maxMin));
        } else {
            res = Math.min(res, Math.max(Math.max(queueMin.peek(), queueMid.peek()), queueMax.peek()) - Math.min(Math.min(minMin, midMin), maxMin));
        }
    }
    System.out.println(res);
}

上述解法时间复杂度O(nlog(n)),空间复杂度O(n)。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值