HWOD Java机试回顾

hwod的机试,三道编程题,难度由易到简,考试时间150分钟,虽然迷迷糊糊但还是AC了,总的来说难度中上吧,我对自己代码的评价是容易理解但可能时间复杂度比较高(但也在题目允许的范围),总的来说可能有点暴力hh,凑合看。

1.A= B + 2C 是否有满足规则的数字组合

题目描述
给定一个正整数数组,检查数组中是否存在满足规则的数字组合
规则: A = B + 2C

输入描述
第一行输出数组的元素个数。
接下来一行输出所有数组元素,用空格隔开。

输出描述
如果存在满足要求的数,在同一行里依次输出规则里A/B/C的取值,用空格隔开。
如果不存在,输出0。

备注
数组长度在3-100之间。
数组成员为0-65535,数组成员可以重复,但每个成员只能在结果算式中使用一次。
如:数组成员为[0, 0, 1, 5],0出现2次是允许的,但结果0 = 0 + 2 * 0是不允许的,因为算式中使用了3个0。
用例保证每组数字里最多只有一组符合要求的解。

示例

输入:
4
2 7 3 0
输出:
7 3 2
说明
7 = 3 + 2 * 2
输入:
3
1 1 1
输出:
0
说明:
找不到满足条件的组合

代码

package cn.myProject;

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        //数据录入
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        Integer[] arr = new Integer[n];
        for(int i = 0; i < n; i++){
            arr[i] = in.nextInt();
        }

        //对数组逆序排序
        Arrays.sort(arr, (o1, o2) -> o2 - o1);

        //思考题目逻辑A=B+2C -> C=(A-B)/2
        //还可得出:A > B和C;A-B是偶数
        int a = 0, b = 0, c = 0;    //初始化A, B, C
        boolean flag = false;   //是否找到了对应数据
        //粗暴遍历,别想太多,由头到尾,由大到小
        for(int i = 0; i < arr.length; i++){
            a = arr[i];
            //A > B且数组逆序,所以初始值为当前i+1即可,也是从头到尾粗暴遍历
            for(int j = i+1; j < arr.length; j++){
                b = arr[j];
                //需要A-B是偶数,C才能为继续求得
                if((a+b)%2 == 0){
                    c = (a - b)/2;
                    int kc = isExist(c, arr);   //查询数组中是否有对应C值,并返回目标C值的下标
                    //要求有C值,且下标与A和B的不重合
                    if(kc > 0 && kc != i && kc != j){
                        //满足条件后设置为true,跳出里循环即可
                        flag = true;
                        break;
                    }
                }
            }
            if(flag){
                //找到后跳出外循环
                break;
            }
        }
        if(!flag){
            System.out.println(0);
        }else{
            System.out.println(a + " " + b + " " + c);
        }
    }

    /**
     *
     * @param c
     * @param arr
     * @return
     */
    private static int isExist(int c, Integer[] arr) {
        //此方法的作用是检验c是否在数组中
        for(int i = 0; i < arr.length; i++){
            if(arr[i] == c){
                return i;
            }
        }
        return -1;
    }
}

废话:很简单捏

2.太阳能板最大面积

题目描述
给航天器一侧加装长方形和正方形的太阳能板(图中的斜线区域)
需要先安装两个支柱(图中的黑色竖条)
再在支柱的中间部分固定太阳能板
但航天器不同位置的支柱长度不同
太阳能板的安装面积受限于最短一侧的那支支柱的长度

现提供一组整型数组的支柱高度数据
假设每个支柱间的距离相等为一个单位长度
计算如何选择两根支柱可以使太阳能板的面积最大

输入描述
10,9,8,7,6,5,4,3,2,1
注释,支柱至少有两根,最多10000根,能支持的高度范围1~10^9的整数

柱子的高度是无序的
例子中的递减是巧合

输出描述
可以支持的最大太阳板面积:(10m高支柱和5m高支柱之间)
25

示例

输入
10,9,8,7,6,5,4,3,2,1
输出
25

备注
10米高支柱和5米高支柱之间宽度为5,高度取小的支柱高度也是5
面积为25
任取其他两根支柱所能获得的面积都小于25 所以最大面积为25。

代码

package cn.myProject;

import java.util.Scanner;

public class Main02 {
    public static void main(String[] args) {
        //数据录入和包装
        //注意:题目高度范围再加上可能到达的根数,我们的面积最好用long,粗暴一点的话,全用long包装就好了
        Scanner in = new Scanner(System.in);
        String[] arrStr = in.nextLine().split(",");
        long[] arr = new long[arrStr.length];
        for(int i = 0; i < arrStr.length; i++){
            arr[i] = Long.parseLong(arrStr[i]);
        }

        //算法本体
        long areaMax = 0;   //当前面积最大值
        long area;  //当前迭代的面积
        //粗暴遍历
        for(int i = 0; i < arr.length; i++){
            for(int j = 0; j < arr.length; j++){
                area = Math.min(arr[i], arr[j]) * (j-i);
                if(area > areaMax){
                    areaMax = area;
                }
            }
        }
        System.out.println(areaMax);
    }
}

废话:简单的要死了

3.删除文件系统目录

某文件系统中有N个目录,每个目录都一个独一无二的ID。每个目录只有一个父目录,但每个父目录下可以有零个或者多个子目录,目录结构呈树状结构。

假设,根目录的ID为0,且根目录没有父目录,其他所有目录的ID用唯一的正整数表示,并统一编号。
现给定目录ID和其父目录ID的对应父子关系表[子目录ID,父目录ID],以及一个待删除的目录ID,请计算并返回一个ID序列,表示因为删除指定目录后剩下的所有目录,返回的ID序列以递增序输出。

注意
1、被删除的目录或文件编号一定在输入的ID序列中;
2、当一个目录删除时,它所有的子目录都会被删除。

输入描述
输入的第一行为父子关系表的长度m;接下来的m行为m个父子关系对;最后一行为待删除的ID。序列中的元素以空格分割,参见样例。

输出描述
输出一个序列,表示因为删除指定目录后,剩余的目录ID。

示例

输入
5
8 6
10 8
6 0
20 8
2 6
8
输出
2 6

题目解析(别人的思路,好像更好一点,我的也不赖啦!)
这个题目是一个树类型的题,但是不是二叉树,所有涉及结构时,需要用一个list保持孩子节点。题目中说明每个目录的id唯一。
TreeMap<Integer, List>保存树结构,key是目录的唯一ID,value是孩子节点的Id的列表。之所以用TreeMap,是因为根据key的从小到大进行排序。后续的输出删除后的目录ID时,就不用再进行排序了
root保存根目录的ID
1、首先构建树保存到上述的TreeMap<Integer, List>
2、根据传入的ID进行树节点的删除,遍历孩子接口进行删除,先删除孩子节点,再删除当前节点。

代码

import java.util.*;

public class Main {
    //保存我们要删除的id
    static List<Integer> list = new LinkedList<>();

    public static void main(String[] args) {
        //数据录入和包装
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        Map<Integer, Integer> map = new HashMap<>();
        for(int i = 0; i < n; i++){
            int key = scanner.nextInt();
            int value = scanner.nextInt();
            map.put(key, value);
        }
        int deleteKey = scanner.nextInt();

        //首先要存到list的就是题目给的id
        list.add(deleteKey);

        //算法:此部分作用用以保存要删除的id到list
        //以此遍历list中的id值,去查找map中value值为当前id的key,再将key加入到list中
        int searchI = 0;    //list中目前我们需要查找其子节点的id的下标
        Set<Integer> keySet = map.keySet();
        while(searchI < list.size()){   //结束条件是遍历完所有id
            for (Integer key : keySet){ //对每个key遍历
                //当map中value == list中下标为searchI的值时,添加到list
                //即:将searchI对应id文件的子文件id添加进去
                if(list.get(searchI) - map.get(key) == 0){//有减号的话就自动拆箱了
                    list.add(key);
                }
            }
            searchI++;  //遍历完成则操作list的下一个id
        }

        //算法:没什么算法,就是用来保存未被删除的元素到finalList并排序
        List<Integer> finalList = new ArrayList<>();
        for(Integer key : keySet){
            //若该key不在list中,则说明没被删除
            if(!list.contains(key)){
                finalList.add(key);
            }
        }
        Collections.sort(finalList);
        
        //输出结果
        for(int i = 0; i < finalList.size(); i++){
            if(i != finalList.size()-1){
                System.out.print(finalList.get(i) + " ");
            }else {
                System.out.print(finalList.get(i));
            }
        }

    }
}

废话:想了一阵子,还好

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值