2020-04-11-快手笔试

一面是四个编程题。

1、匹配括号

给定一字符串,只有’(’,’)’,’+’,’-’,’*’,’/’,数字0~9组成。
实现统计:匹配的正反括号数目,剩余正反括号数目。
如(1+2+3+4+/)((())-+((//*)
返回 4,2,0
4:表示匹配的括号对数是4
2:表示剩余的左括号数是2
0:表示剩余的右括号数是0

分析

  • 使用栈结构,遇到左括号压栈,遇到右括号:如果栈不为空出栈。

代码实现(java)

import java.util.*;
public class Solution {
    public static void main(String[] args) {
        //(1+2+3+4+/)((())-+((//*)
        Scanner sc = new Scanner(System.in);
        String s = sc.next();
        char [] sArr = s.toCharArray();
        //记录匹配数
        int couple = 0;
        //剩余左括号
        int left = 0;
        //剩余右括号
        int right = 0;
        Stack<Character> stack = new Stack<>();
       //遍历字符串
        for (int i = 0; i < sArr.length; i++) {
            //找出(
            if(sArr[i] == '('){
                //入栈
                stack.push(sArr[i]);
            }else if(sArr[i] == ')'){
                //不为空可以匹配
                if(!stack.empty()){
                    stack.pop();
                    couple++;
                }else{
                    //没有匹配的 剩余右括号增加
                    right++;
                }
            }
        }
        //剩余的肯定是左括号
        while(!stack.empty()){
            left++;
            stack.pop();
        }
        System.out.print(couple+" ");
        System.out.print(left+" ");
        System.out.println(right);
    }
}

2、完美数

给定 正整数 R,N。如果 R = N ^ m1+N^m2+…
mi不是重复的数字就可以 。

1、3^ 2 + 3^ 3 + 3^5 =279
279是3的完美数。
输出2 3 5
2、2^ 0 = 1
1是2的完美数。
输出 1
3、3+3 ^2+3 ^2= 19
19不是3的完美数
1 2 2(2重复)
输出 []

分析:

  • 将最大次幂取出,如44,先找出 2^5,保存5
  • 44-2^5 = 12,再从12找出2 ^3,保存3
  • 判断有没重复的。

代码实现(java)

      public static int [] kuaishou2(int R,int N){
        int cur = R;
        ArrayList<Integer> list = new ArrayList<>();
        while(cur > 0){
            int res[] = findMax(cur,N);
            int m = res[0];
            int multi = res[1];
            list.add(m);
            cur -= multi;
        }
        int size = list.size();
        int res [] = new int[size];
        //先看看有没重复的
        for (int i = 0; i < list.size()-1; i++) {
            if(list.get(i) == list.get(i+1)){
                return res;
            }
        }
        //到这就没重复的了 翻位置
        for (int i = 0; i < size; i++) {
            res[size-1-i] = list.get(i);
        }

        for (int i = 0; i < res.length; i++) {
            System.out.println(res[i]);
        }
        return res;
    }

    private static int [] findMax(int cur, int n) {
        // n^m 小于等于cur,而且是最接近的
        int res [] = new int [2];
        int multi = 1;
        int times = 0;
        while(multi <= cur){
            multi *= n;
            times++;
        }
        // res[0] 最高次幂
        //res[1] 对应次幂值
        res[0] = times-1;
        res[1] = multi/n;
        return res;
    }

3、排队问题

有编号为i = 1,2,3~n的人在位置j = 1,2,3 ~ n排队。每个人都希望尽快完事。所以每个人在某一个位置有一个计算公式表示其不满意度: ai*(j-1)+bi*(n-j) ,其中,j表示他处在第j个位置,一共n个位置。ai,bi是每个人自己特有的,会以数组的形式表示,如a=[8,9,7],b=[5,8,3]。这表示1号顾客a1=8,b1=5,如果他排在第一位置,不满意度为8*(1-1)+5*(3-1)。但是卖东西的老板希望所有顾客不满意度加和最低。请给出最优方案。
如:给定 a =[8,9,7],b=[5,8,3]
输出 总不满意度37,顺序2,0,1

分析

  • 首先这是一个排列问题。

java 代码实现

1、


     //总不满意度
    static int unsatisify = Integer.MAX_VALUE;
    //最优顺序
    static int res [] = null;

    public static void kuaishou3(int [] a,int [] b){
        // a= {8,9,7}
        //b={5,8,3}
        //排除非正常输入 略

        res = new int [a.length];

        helper(a,b,new int[a.length],0,new boolean[a.length]);
        System.out.println(unsatisify);
        for (int i = 0; i < res.length; i++) {
            System.out.print(res[i]+" ");
        }

    }
    // seq:当前顺序 cur:到哪了 visited:是否使用过
    public static void helper(int a[],int b[],int seq [] ,int cur,boolean [] visited){
        //次序好了
        if(cur == a.length){
            //计算总不满意度
            int curValue = calculAll(a, b, seq);
            if(curValue < unsatisify){
                unsatisify = curValue;
                for (int i = 0; i < seq.length; i++) {
                    //seq装的是 从0开始的顾客编号 要加1
                    res[i] = seq[i] + 1;
                }
            }
        }else{
            //游标cur处 选择合适顾客
            for (int i = 0; i < visited.length; i++) {
                if(!visited[i]){
                    //没有参与排队
                    visited[i] = true;
                    seq[cur] = i;
                    helper(a,b,seq,cur+1,visited);
                    visited[i] = false;
                }
            }

        }
    }
    //计算某一个顺序的总不满意度    三个数组维度相同 seq数组下标表示位置j=0~ n-1(实际上位置要加1,j+1)
    // 下标j对应的元素,seq[j] 属于(0~n-1)是在该位置的顾客编号,实际上的顾客编号要加1
    //ai*(j-1)+bi*(n-j)
    public static int calculAll(int a[], int [] b,int [] seq){
        int sum = 0;
        for(int j = 0;j < seq.length;j++){
            //j位置 就是第j+1位置
            // no是顾客编号 0~n-1
            int no = seq[j];
            int ai = a[no];
            int bi = b[no];
            //j+1是从1开始的位置
            sum += ai*((j+1)-1) + bi*(seq.length-(j+1));
        }
        return sum;
    }

2、突然想起来,回溯可以提前剪枝!!!现在将helper函数改进如下,调用helperImprove函数时,多了一个curResult表示在curIndex之前排队的顾客总不满意度。如果要将curIndex处放置一顾客后,此时总的不满意度如果超过了当前最优的不满意度,直接舍去该支。

 // seq:当前顺序 cur:到哪了 visited:是否使用过
    public static void helperImprove(int a[],int b[],int seq [] ,int curIndex,boolean [] visited,int curResult){
        //次序好了
        if(curIndex == a.length){
            //计算总不满意度

            if(curResult < unsatisify){
                unsatisify = curResult;
                for (int i = 0; i < seq.length; i++) {
                    //seq装的是 从0开始的顾客编号 要加1
                    res[i] = seq[i] + 1;
                }
            }
        }else{
            //游标cur处 选择合适顾客
            for (int i = 0; i < visited.length; i++) {
                if(!visited[i]){
                    int delta = calculOne(a, b, curIndex, i);
                    if(curResult + delta < unsatisify){
                        //没有参与排队
                        visited[i] = true;
                        seq[curIndex] = i;
                        helperImprove(a,b,seq,curIndex+1,visited,curResult + delta);
                        visited[i] = false;
                    }

                }
            }

        }
    }

    public static int calculOne(int a[], int [] b,int pos,int consumer){

            int ai = a[consumer];
            int bi = b[consumer];
            //j+1是从1开始的位置
           int sum = ai*((pos+1)-1) + bi*(a.length-(pos+1));

        return sum;
    }

4、安排工位

给定一二维数组 char pos[m][n],表示公司的m*n个工位,有的工位有电源,对应数组元素是’+’,有的没有电源,对应元素是’-’。现在想安排员工到有电源得位置。由于疫情影响,每个员工前后左右紧挨着的工位都不能有其他员工。请问最多一共可以安排多少员工?
给定数组 如:[-,+,+,-,-],[+,-,+,-,+],[+,+,+,-,-]
输出 5

分析

  • 使用动态规划,设置一布尔型m*n维二维数组,表示此处是否安排员工
  • 初始化,首先(0,0)处如果有电源就安排。
  • 第0行其他:看自身位置是否有电源,还要看左边相邻有没有安排。
  • 和第0列其他:道理同第0行。
  • 从(1,1)开始,首先看自己有没有电源,还要看上边和左边是否安排了员工。
  • 最后对布尔型数组遍历,将安排员工的位置计数。

java代码

    public static  void kuaishou4(char pos[][]){
        // char pos [][] = {{'-','+','+','-','-'},{'+','-','+','-','+'},{'+','+','+','-','-'}};
        //if() 去除特殊值
        int m = pos.length;
        int n = pos[0].length;
        //默认全false
        boolean gongwei [][] = new boolean[m][n];
        if(pos[0][0] == '+'){
            gongwei[0][0] = true;
        }
        for(int i = 1;i < m;i++){
            //i行0列 如果有电源 而且 上一行0列没有安排员工
            if(pos[i][0] == '+' && !gongwei[i-1][0]){
                gongwei[i][0] = true;
            }
        }

        for(int i = 1;i < n;i++){
            //0行i列 如果有电源 而且 同行上一列没有安排员工
            if(pos[0][i] == '+' && !gongwei[0][i-1]){
                gongwei[0][i] = true;
            }
        }
        for(int i = 1;i < m;i++){
            for(int j = 1;j<n;j++){
                if(pos[i][j] =='+' && !gongwei[i-1][j] && !gongwei[i][j-1]){
                    gongwei[i][j] = true;
                }
            }
        }
        int sum = 0;
        for(int i = 0;i<gongwei.length;i++){
            for(int j=0;j<gongwei[0].length;j++){
                if(gongwei[i][j]){
                    sum++;
                }
            }
        }
        System.out.println(sum);
    }
发布了72 篇原创文章 · 获赞 0 · 访问量 721

猜你喜欢

转载自blog.csdn.net/weixin_40300702/article/details/105474983
今日推荐