2018校招真題【牛客網】練習(八)

1、字節跳動附加題

存在n+1個房間,每個房間依次爲房間1 2 3…i,每個房間都存在一個傳送門,i房間的傳送門可以把人傳送到房間pi(1<=pi<=i),現在路人甲從房間1開始出發(當前房間1即第一次訪問),每次移動他有兩種移動策略:
A. 如果訪問過當前房間 i 偶數次,那麼下一次移動到房間i+1;
B. 如果訪問過當前房間 i 奇數次,那麼移動到房間pi;
現在路人甲想知道移動到房間n+1一共需要多少次移動;

思路:
參考 https://blog.csdn.net/flushhip/article/details/79458502
dp[i] = dp[i-1]+1 // 第一次從i-1移動到i
+1 // 從i傳送到p[i]位置
+dp[i-1] - dp[ p[i]-1 ] - 1 //從p[i]位置移動到i-1
+ 1 //第二次從i-1移動到i
第三步中:dp[ p[i]-1 ]+1可以理解爲,從1到p[i]位置需要移動的步數
代碼:

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] p = new int[n+1];
        for(int i=1;i<=n;i++){
            p[i] = scanner.nextInt();
        }
        scanner.close();
        long dp[] = new long[n+1];
        for(int i=1;i<=n;i++){
            dp[i] = (dp[i-1]*2%1000000007-dp[p[i]-1]+2)%1000000007;
        }
        System.out.println(dp[n]%1000000007);
    }
}

2、字節跳動編程題1

題目描述:
有三隻球隊,每隻球隊編號分別爲球隊1,球隊2,球隊3,這三隻球隊一共需要進行 n 場比賽。現在已經踢完了k場比賽,每場比賽不能打平,踢贏一場比賽得一分,輸了不得分不減分。已知球隊1和球隊2的比分相差d1分,球隊2和球隊3的比分相差d2分,每場比賽可以任意選擇兩隻隊伍進行。求如果打完最後的 (n-k) 場比賽,有沒有可能三隻球隊的分數打平。

思路:
分類討論。

代碼:

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int t = scanner.nextInt();
        for(int i=0;i<t;i++){
            boolean isSame = 
                possibleSame(scanner.nextLong(),scanner.nextLong()
                             ,scanner.nextLong(),scanner.nextLong());
            if(isSame){
                System.out.println("yes");
            }else{
                System.out.println("no");
            }
        }
        scanner.close();
    }
    public static boolean possibleSame(long n,long k,long d1,long d2){
        // 1 < 2 < 3
        long temp = k-d1-(d1+d2);
        if(temp>=0&&temp%3==0){
            long left = n-k-(d1+d2+d2);
            if(left>=0&&left%3==0){
                return true;
            }
        }
        // 1 < 2 > 3
        if(d1+d1-d2<0){
            temp = k-(d2+d2-d1);
        }else if(d2+d2-d1<0){
            temp = k-(d1+d1-d2);
        }else{
            temp = k-Math.min(d1+d1-d2,d2+d2-d1);
        }
        if(temp>=0&&temp%3==0){
            long left = n-k-(d1+d2);
            if(left>=0&&left%3==0){
                return true;
            }
        }
        // 1 > 2 > 3
        temp = k-d2-(d1+d2);
        if(temp>=0&&temp%3==0){
            long left = n-k-(d1+d1+d2);
            if(left>=0&&left%3==0){
                return true;
            }
        }
        // 1 > 2 < 3
        temp = k-d1-d2;
        if(temp>=0&&temp%3==0){
            long left = n-k-Math.max(d1+d1-d2,d2+d2-d1);
            if(left>=0&&left%3==0){
                return true;
            }
        }
        return false;
    }
}

3、字節跳動編程題2

題目描述:
有一個僅包含’a’和’b’兩種字符的字符串s,長度爲n,每次操作可以把一個字符做一次轉換(把一個’a’設置爲’b’,或者把一個’b’置成’a’);但是操作的次數有上限m,問在有限的操作數範圍內,能夠得到最大連續的相同字符的子串的長度是多少。

思路:
以替換a爲例,那麼我們需要找到所有a的位置pos[n],連續的最長的b就是a[i+m+1]-a[i]-1中最長的那一個子序列。

代碼:

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        scanner.nextLine();
        char[] str = scanner.nextLine().toCharArray();
        System.out.println(Math.max(getLength(n,m,str,'a'),getLength(n,m,str,'b')));
    }
    public static int getLength(int n,int m,char[] str,char c){
        ArrayList<Integer> pos = new ArrayList<>();
        for(int i=0;i<n;i++){
            if(str[i]==c){
                pos.add(i);
            }
        }
        if(pos.size()<=m){
            return n;
        }
        pos.add(str.length);
        int result = pos.get(m);
        for(int i=m+1;i<pos.size();i++){
            result = Math.max(result,pos.get(i)-pos.get(i-m-1)-1);
        }
        return result;
    }
}

4、字節跳動附加題

題目描述:
二階魔方又叫小魔方,是222的立方形結構。每一面都有4個塊,共有24個塊。每次操作可以將任意一面逆時針或者順時針旋轉90°,如將上面逆時針旋轉90°操作如下。
在這裏插入圖片描述
Nero在小魔方上做了一些改動,用數字替換每個塊上面的顏色,稱之爲數字魔方。魔方上每一面的優美度就是這個面上4個數字的乘積,而魔方的總優美度就是6個面優美度總和。
現在Nero有一個數字魔方,他想知道這個魔方在操作不超過5次的前提下能達到的最大優美度是多少。
魔方展開後每一塊的序號如下圖:
在這裏插入圖片描述
思路:
參考 https://blog.csdn.net/cswhit/article/details/87110959
寫出六個面轉動的交換,利用遞歸求最大值

代碼:

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNextInt()){
            int[] num = new int[24];
            for(int i=0;i<24;i++){
                num[i] = scanner.nextInt();
            }
            System.out.println(maxGrace(num,5));
        }
    }
    public static int maxGrace(int[] num,int times){
        int grace = calculateGrace(num);
        if(times==0){
            return grace;
        }
        int[] numcp = new int[24];
        for(int i=0;i<24;i++){
            numcp[i] = num[i];
        }
        turnLeft(numcp);
        grace = Math.max(maxGrace(numcp,times-1),grace);
        for(int i=0;i<24;i++){
            numcp[i] = num[i];
        }
        turnRight(numcp);
        grace = Math.max(maxGrace(numcp,times-1),grace);
        for(int i=0;i<24;i++){
            numcp[i] = num[i];
        }
        turnTop(numcp);
        grace = Math.max(maxGrace(numcp,times-1),grace);
        for(int i=0;i<24;i++){
            numcp[i] = num[i];
        }
        turnBottom(numcp);
        grace = Math.max(maxGrace(numcp,times-1),grace);
        for(int i=0;i<24;i++){
            numcp[i] = num[i];
        }
        turnFront(numcp);
        grace = Math.max(maxGrace(numcp,times-1),grace);
        for(int i=0;i<24;i++){
            numcp[i] = num[i];
        }
        turnBack(numcp);
        grace = Math.max(maxGrace(numcp,times-1),grace);
        return grace;
    }
    public static void turnLeft(int[] num){
        change(num,0,6,16,20);
        change(num,2,12,18,22);
        change(num,4,5,11,10);
    }
    public static void turnRight(int[] num){
        change(num,1,7,17,21);
        change(num,3,13,19,23);
        change(num,9,8,14,15);
    }
    public static void turnTop(int[] num){
        change(num,4,6,8,23);
        change(num,5,7,9,22);
        change(num,2,3,1,0);
    }
    public static void turnBottom(int[] num){
        change(num,10,12,14,21);
        change(num,11,13,15,20);
        change(num,16,17,19,18);
    }
    public static void turnFront(int[] num){
        change(num,11,2,8,17);
        change(num,5,3,14,16);
        change(num,6,7,13,12);
    }
    public static void turnBack(int[] num){
        change(num,10,0,9,19);
        change(num,4,1,15,18);
        change(num,22,23,21,20);
    }
    public static void change(int[] num,int i,int j,int k,int m){
        int temp = num[i];
        num[i] = num[j];
        num[j] = num[k];
        num[k] = num[m];
        num[m] = temp;
    }
    
    public static int calculateGrace(int[] n){
        return n[0]*n[1]*n[2]*n[3]
                +n[4]*n[5]*n[10]*n[11]
                +n[8]*n[9]*n[14]*n[15]
                +n[6]*n[7]*n[12]*n[13]
                +n[16]*n[17]*n[18]*n[19]
                +n[20]*n[21]*n[22]*n[23];
    }
}

5、字節跳動編程題1

題目描述:
有一個推箱子的遊戲, 一開始的情況如下圖:
在這裏插入圖片描述
上圖中, ‘.’ 表示可到達的位置, ‘#’ 表示不可到達的位置,其中 S 表示你起始的位置, 0表示初始箱子的位置, E表示預期箱子的位置,你可以走到箱子的上下左右任意一側, 將箱子向另一側推動。如下圖將箱子向右推動一格;
…S0… -> …S0.
注意不能將箱子推動到’#'上, 也不能將箱子推出邊界;
現在, 給你遊戲的初始樣子, 你需要輸出最少幾步能夠完成遊戲, 如果不能完成, 則輸出-1。

思路:
參考 https://blog.csdn.net/yuanxu716/article/details/78286266
(還沒有完全理解,待以後補充)

代碼:

import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;

public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNextLine()){
            String[] token = scanner.nextLine().split(" ");
            int n = Integer.parseInt(token[0]);
            int m = Integer.parseInt(token[1]);
            char[][] matrix = new char[n][m];
            int x = -1,y = -1,bx = -1,by = -1;
            for(int i=0;i<n;i++){
                String input = scanner.nextLine();
                for(int j=0;j<m;j++){
                    matrix[i][j] = input.charAt(j);
                    if(matrix[i][j]=='S'){
                        x=i;
                        y=j;
                    }
                    if(matrix[i][j]=='0'){
                        bx=i;
                        by=j;
                    }
                }
            }
            ArrayList<ArrayList<Integer>> next = new ArrayList<>();
            //{-1,0},{1,0},{0,-1},{0,1}
            ArrayList<Integer> a1 = new ArrayList<>();
            a1.add(-1);a1.add(0);
            ArrayList<Integer> a2 = new ArrayList<>();
            a2.add(1);a2.add(0);
            ArrayList<Integer> a3 = new ArrayList<>();
            a3.add(0);a3.add(-1);
            ArrayList<Integer> a4 = new ArrayList<>();
            a4.add(0);a4.add(1);
            next.add(a1);
            next.add(a2);
            next.add(a3);
            next.add(a4);
            //System.out.println(next);
            ConcurrentLinkedQueue<ArrayList<Integer>> queue = new ConcurrentLinkedQueue<>();
            ArrayList<Integer> a = new ArrayList<>();
            a.add(x);a.add(y);a.add(bx);a.add(by);
            queue.offer(a);
            //System.out.println(queue);
            int st[][][][] = new int[50][50][50][50];
            st[x][y][bx][by] = 1;
            while(!queue.isEmpty()){
                ArrayList<Integer> pb = queue.poll();
                x = pb.get(0);
                y = pb.get(1);
                bx = pb.get(2);
                by = pb.get(3);
                for(int i=0;i<next.size();i++){
                    int nx = x+next.get(i).get(0),
                            ny = y+next.get(i).get(1);
                    int nnx = nx+next.get(i).get(0),
                            nny = ny+next.get(i).get(1);
                    // 玩家從開始位置走到箱子的位置
                    if(valid(matrix,nx,ny)&&(nx!=bx||ny!=by)&&st[nx][ny][bx][by]==0){
                        st[nx][ny][bx][by] = st[x][y][bx][by]+1;
                        ArrayList<Integer> list = new ArrayList<>();
                        list.add(nx);list.add(ny);list.add(bx);list.add(by);
                        queue.offer(list);
                        continue;
                    }
                    // 玩家把箱子推到指定位置
                    else if(valid(matrix,nnx,nny)&&(nx==bx&&ny==by)&&st[nx][ny][nnx][nny]==0){
                        st[nx][ny][nnx][nny] = st[x][y][bx][by]+1;
                        if(matrix[nnx][nny]=='E'){
                            System.out.println(st[nx][ny][nnx][nny]-1);
                            return;
                        }
                        ArrayList<Integer> list = new ArrayList<>();
                        list.add(nx);list.add(ny);list.add(nnx);list.add(nny);
                        queue.offer(list);
                    }
                }

            }
            System.out.println(-1);
            return;
        }
    }
    public static boolean valid(char[][] matrix,int x,int y){
        if (x >= 0 && x < matrix.length && y >= 0 && y < matrix[0].length && matrix[x][y] != '#')
            return true;
        return false;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章