拼多多2017秋招编程

一、
给定一个无序数组,包含正数、负数和0,要求从中找出3个数的乘积,使得乘积最大,要求时间复杂度:O(n),空间复杂度:O(1)
输入描述:
无序整数数组A[n]
输出描述:
满足条件的最大乘积
示例1
输入
3 4 1 2
输出
24

public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n = sc.nextInt();
        /* 两种情况:1、三个数都是正数,取三个最大整数
         *           2、两个最小负数和一个最大正数
         */
        int max[] = new int[3];
        int min[] = new int[2];
        Arrays.fill(max, Integer.MIN_VALUE);
        Arrays.fill(min, Integer.MAX_VALUE);
        for (int i = 0; i < n; i++) {
            int cur = sc.nextInt();
            if(cur > max[0]) {
                max[2] = max[1];
                max[1] = max[0];
                max[0] = cur;
            } else if(cur > max[1]) {
                max[2] = max[1];
                max[1] = cur;
            } else if(cur > max[2]) {
                max[2] = cur;
            }
            if(cur < min[0]) {
                min[1] = min[0];
                min[0] = cur;
            } else if(cur < min[1]) {
                min[1] = cur;
            }
        }
        System.out.println(Math.max((long)min[0]*min[1]*max[0], (long)max[0]*max[1]*max[2]));
        sc.close();
    }
}

二、
有两个用字符串表示的非常大的大整数,算出他们的乘积,也是用字符串表示。不能用系统自带的大整数类型。
输入描述:
空格分隔的两个字符串,代表输入的两个大整数
输出描述:
输入的乘积,用字符串表示
示例1
输入
72106547548473106236 982161082972751393
输出
70820244829634538040848656466105986748

public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        String a = sc.next();
        String b = sc.next();
        sc.close();
        int result[] = new int[a.length() + b.length()];//两个数相乘,结果的位数必小于两个数位数之和
        int n = a.length();
        int m = b.length();
        a = new StringBuilder(a).reverse().toString();
        b = new StringBuilder(b).reverse().toString();
        for(int i = 0; i < n; i++) {//先算没有进位的两个数相乘
            for(int j = 0; j < m; j++) {
                result[i + j] += (a.charAt(i) - '0') * (b.charAt(j) - '0');
            }
        }
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < result.length; i++) {//处理进位问题
            int remain = result[i] % 10;
            int carry = result[i] / 10;
            sb.append(remain);
            if(i < result.length - 1) {//防止数组越界
                result[i + 1] += carry;
            }
        }
        sb.reverse();//处理顺序是尾部在头,所以应该反转
        while(sb.length() > 0 && sb.charAt(0) == '0') {//result数组长度可能稍大,最后几个数为0
            sb.deleteCharAt(0);
        }
        System.out.println(sb.toString());
    }
}

三、
六一儿童节,老师带了很多好吃的巧克力到幼儿园。
每块巧克力j的重量为w[j],对于每个小朋友i,当他分到的巧克力大小达到h[i] (即w[j]>=h[i]),他才会上去表演节目。
老师的目标是将巧克力分发给孩子们,使得最多的小孩上台表演。可以保证每个w[i]> 0且不能将多块巧克力分给一个孩子或将一块分给多个孩子。
输入描述:
第一行:n,表示h数组元素个数
第二行:n个h数组元素
第三行:m,表示w数组元素个数
第四行:m个w数组元素
输出描述:
上台表演学生人数
示例1
输入
3
2 2 3
2
3 1
输出
1

public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n = sc.nextInt();
        int h[] = new int[n];
        for(int i = 0; i < n; i++) {
            h[i] = sc.nextInt();
        }
        int m = sc.nextInt();
        int w[] = new int[m];
        for(int i = 0; i < m;i++) {
            w[i] = sc.nextInt();
        }
        sc.close();
        //给需求最少的人最小的巧克力
        Arrays.sort(h);
        Arrays.sort(w);
        int res = 0;
        for(int i = m - 1, j = n - 1; i >= 0 && j >= 0; j--) {
            if(w[i] >= h[j]) {
                res++;
                i--;
            }
        }System.out.println(res);
    }
}

四、
假设一个探险家被困在了地底的迷宫之中,要从当前位置开始找到一条通往迷宫出口的路径。
迷宫可以用一个二维矩阵组成,有的部分是墙,有的部分是路。
迷宫之中有的路上还有门,每扇门都在迷宫的某个地方有与之匹配的钥匙,只有先拿到钥匙才能打开门。
请设计一个算法,帮助探险家找到脱困的最短路径。
如前所述,迷宫是通过一个二维矩阵表示的,每个元素的值的含义如下
0-墙,1-路,2-探险家的起始位置,3-迷宫的出口,大写字母-门,小写字母-对应大写字母所代表的门的钥匙
输入描述:
迷宫的地图,用二维矩阵表示。第一行是表示矩阵的行数和列数M和N
后面的M行是矩阵的数据,每一行对应与矩阵的一行(中间没有空格)。M和N都不超过100, 门不超过10扇。
输出描述:
路径的长度,是一个整数
输入
5 5
02111
01a0A
01003
01001
01111
输出
7

class Point {
    int x;
    int y;
    int key;
    public Point(int x, int y, int key) {
        this.x = x;
        this.y = y;
        this.key = key;
    }
}
public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int m = sc.nextInt();
        int n = sc.nextInt();
        char map[][] = new char[m][n];
        sc.nextLine();
        for (int i = 0;i<m;i++){
            map[i] = sc.nextLine().toCharArray();
        }
        sc.close();
        //迷宫问题一般都是用dfs。本题和一般的迷宫问题差别在找钥匙
        int startx = 0, starty = 0, endx = 0, endy = 0;
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < n; j++) {
                if(map[i][j] == '2') {//找起点
                    startx = i;
                    starty = j;
                }
                if(map[i][j] == '3') {//找终点
                    endx = i;
                    endy = j;
                }
            }
        }
        System.out.println(bfs(map, m, n, startx, starty, endx, endy));
    }

    private static int bfs(char[][] map, int m, int n, int startx, int starty, int endx, int endy) {
        Queue<Point> q = new LinkedList<>();
        int dir[][] = {{0,1}, {0,-1}, {1,0}, {-1,0}};//每行一个方向
        int[][][] keys = new int[m][n][1024];//keys存路径长度。最多10把钥匙,用十个01串存获取钥匙情况
        for (int i = 0;i < m; i++){
            for (int j = 0;j < n; j++){
                for (int s = 0;s < 1024; s++){
                    keys[i][j][s] = -1;//初始化为-1表示未走过
                }
            }
        }
        q.add(new Point(startx, starty, 0));
        keys[startx][starty][0] = 0;
        while (!q.isEmpty()){
            Point next = q.poll();
            int x = next.x;
            int y = next.y;
            int key = next.key;
            if (x == endx && y == endy) {//走到终点
                //每遍历一层路径都加1,所以最先到达终点的可认为路径最短
                return keys[x][y][key];
            }
            for (int i = 0; i < 4; i++){
                x = next.x + dir[i][0];
                y = next.y + dir[i][1];
                key = next.key;
                if(x < 0 || x >= m || y < 0 || y >= n || map[x][y] == '0') {//走出界或走到墙
                    continue;
                }
                if(keys[x][y][key] != -1) {//当前路径走过
                    continue;
                }
                if(map[x][y] >= 'a' && map[x][y] <= 'z'){//走到钥匙
                    key = key | (0x1 << (map[x][y] - 'a'));
                }
                if (map[x][y] >= 'A' && map[x][y] <= 'Z'){//走到门
                    if((key & (0x1 << (map[x][y] - 'A'))) <= 0){//没有钥匙
                        continue;
                    }
                }

                keys[x][y][key] = keys[next.x][next.y][next.key]+1;//标记是否走过,MAX表示未走过
                q.add(new Point(x,y,key));
            }
        }
        return -1;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值