华为校招机测(8-25)

华为机测,本来以为是2个hard + 1个medium;

结束后一查才发现,第一题就是hard,不讲武德啊!

好家伙,三个hard!华为机测容易的时代一去不复返了!!!

第一题:  最大值子矩阵

题目给出一个矩阵,里面的值有正有负,

求一个子矩阵,使得这个子矩阵框住的值最大,并返回最大值。

//这一题的思路是:由一维的连续子数组最大和,然后扩展到上下界的遍历,则可计算二维问题。//复杂度O(N^3)

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int rows = sc.nextInt();//行数
        int cols = sc.nextInt();//列数
        int res = Integer.MIN_VALUE;
        int[][]matrix = new int[rows][cols];
        for(int i=0; i<=rows-1; ++i){
            for(int j=0; j<=cols-1; ++j){
                matrix[i][j] = sc.nextInt();
            }
        }
        for(int begin = 0; begin<=rows-1; ++begin){//上边界
            int[] line = new int [cols];//每一列之和 //修改上边界之后,要清空重新开始
            for(int end = begin; end<= rows-1; ++end){//下边界
                //计算列元素和
                for(int j=0; j<=cols-1; ++j){
                    line[j] += matrix[end][j];//下边界每向下一行,就计算更新下line[]数组的值
                }
                res = Math.max(res,line[0]);
                int sum = 0;
                for(int j=0; j<=cols-1; ++j){
                    sum += line[j];
                    res = Math.max(res,sum);//取最大
                    if(sum<0)sum=0;//小于零,置零  //这样意味着最终的值可能是负数
                }
            }
        }
        System.out.println(res);
    }
}
//3 4
//-3 5 -1 5
//2 4 -2 4
//-1 3 -1 3

////20

 

 

第二题:  逃跑路径长度

给出一个矩阵,里面是秒数,

从左上出发,到右下结束,每走一格,所有秒数都减一

求逃跑路径的长度(路径长度==逃跑总时间,一秒一格)

import java.io.BufferedInputStream;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

class Node{
    int x;
    int y;
    int hop;
    public Node(int x, int y, int hop) {
        this.x = x;
        this.y = y;
        this.hop = hop;
    }
}

public class Main {
    static int row,col;
    static int[] dx={-1,1,0,0};
    static int[] dy={0,0,1,-1};

    private static int getAns(int[][] grid){
        if (grid[0][0]<=0){
            return -1;
        }
        int[][] minTime=new int[row][col];
        for (int i = 0; i < row; i++) {
            Arrays.fill(minTime[i],Integer.MAX_VALUE);
        }
        Queue<Node> queue=new LinkedList<>();
        queue.add(new Node(0,0,0));
        while (!queue.isEmpty()){
            Node node=queue.poll();
            int x=node.x;
            int y=node.y;
            int hop=node.hop;
//            System.out.println(x+" "+y+" "+hop);
            if (minTime[x][y]<=hop||grid[x][y]<hop)continue;
            minTime[x][y]=hop;
            if (x==row-1&&y==col-1)return hop;
            for (int i = 0; i < dx.length; i++) {
                int nextX=dx[i]+x;
                int nextY=dy[i]+y;
                if (!inGrid(nextX,nextY))continue;
                queue.add(new Node(nextX,nextY,hop+1));
            }
        }
        return -1;
    }
    private static boolean inGrid(int x,int y){
        return x>=0&&x<row&&y>=0&&y<col;
    }

    //Main主函数
    public static void main(String[] args) {
        Scanner s=new Scanner(new BufferedInputStream(System.in));
        row=s.nextInt();
        col=s.nextInt();
        int[][] grid=new int[row][col];
        for (int i = 0; i <row ; i++) {
            for (int j = 0; j < col; j++) {
                grid[i][j]=s.nextInt();
            }
        }
        System.out.println(getAns(grid));
    }
}
//如果想快速取分,直接return row+col-2, 可以得到90%的分,惊不惊喜!!!

 

 

第三题:  任务规划(类似AOE)

题目给出多个任务,包括每个任务需要的时间,

以及所有任务依赖的其他任务,依赖的其他任务完成后才能执行本任务,

求完成所有任务所需的时间,如果任务循环依赖等待则返回-1

 

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;
// 【任务类型划分】
// 将任务划分为task+run+finish三个状态:task是未达到运行条件的任务; run是正在运行的任务; finish是已完成的任务;
// 由于task需要保存任务的多个依赖项,且后续需要remove删除依赖,所以使用ArrayList<HashSet<Integer>>
// run和finish均使用 HashSet<Integer>
// 【模拟思路】
// 以时间time为主线,一秒一秒加,直到全部运行完则返回总时间;如果总时间大于1000则认为是有循环依赖返回-1
// 【状态转换】
// 1) 检查所有finish,去掉task中的依赖项;(初始状态下,finish有-1)
// 2) 检查每个task,将依赖为空的,放到run里面(hashSet自动去重了)
// 3) 遍历所有run,把对应的任务ArrayList<Integer> time用时都减一;
// 4) 如果任务剩余时间减到0,就放入finish
// 5) 循环的最后判断finish的size是否是num+1(有一个-1),如果是就跳出循环、所有任务结束
// 6) 时间+1,从头循环

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        ArrayList<HashSet<Integer>> task = new ArrayList<HashSet<Integer>>();//存task任务依赖
        ArrayList<Integer> time = new ArrayList<>();//存时间
        for(int i=0; i<=num-1; ++i){
            String str1 = sc.next();
            String str2 = sc.next();
            String[] strs = str1.split(",");
            HashSet<Integer> task1 = new HashSet<>();
            task.add(task1);

            for(String s:strs){
                task.get(i).add(Integer.valueOf(s));
            }
            //任务
            time.add(Integer.valueOf(str2));
        }

        HashSet<Integer> finish = new HashSet<>();//完成的任务
        finish.add(-1);
        HashSet<Integer> run = new HashSet<>();

        int res = 0;

        for(;res<=1000;res++){
            //检查finish
            for(Integer f:finish){
                for(int i=0;i<=num-1;++i){
                    task.get(i).remove(f);
                }
            }
            for(int i=0;i<=num-1;++i){
                if(task.get(i).size()==0)run.add(i);
            }
            for(Integer r:run){
                int newValue = time.get(r)-1;
                time.set(r,newValue);
                if(time.get(r)==0)finish.add(r);
            }
            if(finish.size()==num+1){
                res++;
                break;
            }
        }
        if(res == 1001)res =-1;
        System.out.println(res);
    }
}
//===用例1===//
//6
//3,5 2
//5 3
//4 5
//1 2
//0 3
//-1 1

////16


//===用例2===//
//3
//-1 1
//2 2
//1 3

////-1

//===用例3===//
//3
//-1 1
//-1 2
//-1 3

////3

 

posted @ 2021-08-31 11:36  青杨风2199  阅读(236)  评论(0编辑  收藏  举报