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;
}
}