JAVA入门算法题(十五)

一、满二叉搜索树

/**
 * 给定一个二叉树的层序遍历判断是不是一颗满二叉搜索树
 */

大致分为这么几步:

1.处理输入

2.根据满二叉树的节点数量进行排除

3.构建树

4.递归判断

    public static Node root;
    public static void isManTree(){
        Scanner sc = new Scanner(System.in);
        ArrayList<Integer> integers=new ArrayList<>();
        while (sc.hasNextInt()) {
            integers.add(sc.nextInt());
        }
        if (integers.size()<2){
            System.out.println("True");
            return;
        }else if (integers.size()%2==0){
            System.out.println("False");
            return;
        }
        int size=integers.size()+1;
        while (size!=1){
            if (size%2!=0){
                System.out.println("False");
                return;
            }
            size/=2;
        }
        root=new Node(integers.get(0));
        creatTree(root,integers);
        if (isMantree(root)){
            System.out.println("True");
        }else {
            System.out.println("False");
        }
    }

    private static void creatTree(Node root, ArrayList<Integer> integers) {
        LinkedBlockingQueue<Node> nodes=new LinkedBlockingQueue<Node>();
        nodes.add(root);
        int num=1,index=0,length=integers.size();
        while (index+1<length){
            for (int i=0;i<num;i++){
                Node node=nodes.poll();
                System.out.println(num+"  "+index);
                Node left=new Node(integers.get(++index));
                Node right=new Node(integers.get(++index));
                node.left=left;
                node.right=right;
                nodes.offer(left);
                nodes.offer(right);
            }
            num*=2;
        }
    }


    public static boolean isMantree(Node root){
        if (root.left==null||root.right==null)return true;
        if (root.left.value>root.value||root.right.value<root.value){
            return false;
        }
        return isMantree(root.left)&&isMantree(root.right);
    }


    static class Node{
        int value;
        Node left;
        Node right;
        Node(int value){
            this.value=value;
        }
    }

其实可以再优化一下,在构建树的时候就判断是否满足二叉搜索树的条件

二、次品率

题目:

/**
 * 穷否病食品加工厂今年产品质量出现了大问题!它所包装生产的苹果一箱按标准应该是6±0.1公斤(6000±100克),
 * 但是因为生产流水线出现了一些无法排查的问题,有些产品会缺斤少两,如果一箱苹果少于5900克,则视为次品。
 * 现在给你一批产品每箱的重量,你需要计算这批产品的次品率是多少。
 *
 * 输入
 * 第一行一个数n,表示苹果的箱数。
 * 接下来一行n个整数(以克为单位),第i个数表示第i箱的重量。
 * 输出
 * 输出一个百分数(保留两位小数,四舍五入)。具体参见样例。
 *
 * 样例输入
 * 5
 * 5900 6100 6000 6101 5899
 * 样例输出
 * 20.00%
 *
 * 提示
 * 输入样例2
 * 6
 * 5900 6100 6000 6101 5899 6010
 *
 * 输出样例2
 * 16.67%
 */

此题为百度2020届Android实习生的笔试题,题很简单,主要的问题在四舍五入和保留两位小数上

注意这样的一种情况,当次品率为25%时,要输出25.00%而不是25.0%

    public static void errorRate() {
        Scanner scanner = new Scanner(System.in);
        int num = scanner.nextInt();
        int[] nums = new int[num];
        for (int i = 0; i < num; i++) {
            nums[i] = scanner.nextInt();
        }
        float error = 0;
        for (int apple : nums) {
            if (apple < 5900) {
                error++;
            }
        }
        float errorRate = (error * 100) / num;
        double realErrorRate = Math.round(errorRate * 100) / 100.0;
        String string = String.valueOf(realErrorRate);
        int index = string.indexOf(".");
        if (string.length() - index < 3) {
            System.out.println(realErrorRate + "0%");
        } else {
            System.out.println(realErrorRate + "%");
        }
        scanner.close();
    }

三、最大战力

题目:

/**
 * 有一个军团要打仗,有n名士兵(一定是3的倍数),每一个士兵都有自己的物理攻击力和魔法攻击力,
 * 要分成三个等大的小队派去三块空间打仗,物理空间只能发挥物理攻击力,魔法空间只能发挥魔法攻击力,
 * 虚无空间只能发挥物理攻击力,魔法攻击力之和的一半,你要进行合理的分配使三个小队的总战力最大,
 * 问最大是多少?
 */

这道题也是百度2020届Android实习生的笔试题

要使总的战力之和最大,那么问题的核心就在如何使战力损失最小上,也就是说一个士兵去所在的战场上的价值最高

比如说有两个士兵分别为 甲(5,2)和乙(6,9),那么甲士兵明显适合去物理战场,及时乙士兵的物理战力更高,但是应该让每个士兵发挥每个士兵的长处,而不是单纯看一方面

那么思路就清楚了,这道题有两种解法,最暴力的就是全排列,让前n/3的人去物理空间,中间n/3的人去魔法空间,后n/3的人去虚无空间,其实顺序无所谓,主要是覆盖所有分配情况,但是这样写比较麻烦而且效率特别低下

还有一种解法就是让各自发挥自己的最大价值,用一个数组存储各自的物理战力减去魔法战力,然后进行从小到大排序,这样前面的人就是物理攻击力远高于魔法攻击力的,让他们去物理空间最合适了,这样就把去物理空间的n/3的人订好了,最后的人肯定是魔法高于物理的,适合去魔法空间,那去魔法空间的人也订好了,剩下中间n/3的人去虚无,这里要注意一下,因为物理战力加魔法战力之和除以2可能有小数,这也要考虑到,不能白白损失,所以这里要用float计算。

其中还有一个问题就是对物理魔法差值排序时,要同时保存对应的下标,别把士兵对应的值弄错了

public static void maxPower(int n,int[] wuli,int[] mofa){
        int[] chazhi=new int[n];
        int[] index=new int[n];
        for (int i=0;i<n;i++){
            chazhi[i]=wuli[i]-mofa[i];
            index[i]=i;
        }
        int temp;
        for (int i = 0; i < n; i++) {//冒泡趟数
            for (int j = 0; j < n - i - 1; j++) {
                if (chazhi[j] < chazhi[j+1]) {
                    temp = chazhi[j];
                    chazhi[j] = chazhi[j + 1];
                    chazhi[j + 1] = temp;
                    temp=index[j];
                    index[j]=index[j+1];
                    index[j+1]=temp;
                }
            }
        }
        for (int a:chazhi){
            System.out.print(a+"  ");
        }
        System.out.println();
        for (int a:index){
            System.out.print(a+"  ");
        }
        System.out.println();
        float maxPower=0;
        int xuwuPower=0;
        for (int i=0;i<n;i++){
            if (i<n/3){
                maxPower+=wuli[index[i]];
            }else if (i<n*2/3){
                xuwuPower+=wuli[index[i]]+mofa[index[i]];
            }else {
                maxPower+=mofa[index[i]];
            }
        }
        maxPower+=xuwuPower/2.0;
        System.out.println(maxPower);
    }

四、小Q喝果汁

题目:

/**
 *小Q的父母要出差,留给小Q n 瓶饮料,他们的容量为v[i]毫升,小Q想先喝s毫升,
 * 但是他想让剩下的饮料中最少的尽可能的多,问最少的饮料是多少毫升
 * 不足返回-1
 * 例:
 * 输入:
 * 3 5
 * 1 1 1
 * 输出:
 * -1
 * 输入:
 * 2 9
 * 5 10
 * 输出:
 * 3
 */

这道题是腾讯2020届Android实习生笔试题

这道题需要注意的一点便是瓶子的容量,你可以随便的倒饮料,但是不能把超过瓶子容量的果汁倒进瓶子中

要想求最少的饮料是多少,那这个值一定小于等于最小的瓶子容量

总体思路:求出最小容量,喝掉比最小容量多的果汁,没喝够就不断每瓶喝1毫升,喝够了返回最小值

首先一个for循环求出最小容量和总饮料数量

如果总饮料数量小于s,说明不够喝 打印-1

如果总饮料数量减去s小于瓶数,那么肯定有空瓶 打印0

喝掉比最小容量多的饮料,如果没喝够就每瓶喝一毫升,最小容量减1

打印最小容量

    private static void drinkJuice(int n,int[] v,int s){
        int current=0;
        int min=Integer.MAX_VALUE;
        int count=0;
        for (int i=0;i<n;i++){
            if (min>v[i]){
                min=v[i];
            }
            count+=v[i];
        }
        if (count<s){
            System.out.println(-1);
            return;
        }else if (count-s<n){
            System.out.println(0);
            return;
        }
        for (int i=0;i<n;i++){
            current+=v[i]-min;
        }
        while (current<s){
            min--;
            current+=n;
        }
        System.out.println(min);
    }

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幽蓝丶流月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值