【京東】2016研發工程師(第一題沒做出來,動態規劃類似公共子串重點,反覆看;第三題沒有做出來自我檢討)
[程式設計題]年終獎
小東所在公司要發年終獎,而小東恰好獲得了最高福利,他要在公司年會上參與一個抽獎遊戲,遊戲在一個6*6的棋盤上進行,上面放著36個價值不等的禮物,每個小的棋盤上面放置著一個禮物,他需要從左上角開始遊戲,每次只能向下或者向右移動一步,到達右下角停止,一路上的格子裡的禮物小東都能拿到,請設計一個演算法使小東拿到價值最高的禮物。
給定一個6*6的矩陣board,其中每個元素為對應格子的禮物價值,左上角為[0,0],請返回能獲得的最大價值,保證每個禮物價值大於100小於1000。
這道題類似與公共子串那道題,一開始我以為是回溯法,就參考了滴滴小青蛙的題,結果通過率3.33%
錯誤解法如下:
import java.util.*; public class Bonus { static int max = Integer.MIN_VALUE; public int getMost(int[][] board) { // write code here generate(board, 0, 0, board[0][0]); return max; } private void generate(int[][] map, int x, int y, int salary) { if (x == map.length - 1 && y == map.length - 1) { if (salary > max) { max = salary; return; } } // 走過得用0標記 int temp = map[x][y];// 記錄儀xy裡面的錢數 map[x][y] = 0; // 右 if (x < map.length - 1 && map[x + 1][y] != 0) { generate(map, x + 1, y, salary + map[x + 1][y]); } // 下 if (y < map.length - 1 && map[x][y + 1] != 0) { generate(map, x, y + 1, salary + map[x][y + 1]); } // 還原回去 map[x][y] = temp; } }
正確思路:
連結:https://www.nowcoder.com/questionTerminal/72a99e28381a407991f2c96d8cb238ab
來源:牛客網
平面上有N*M個格子,每個格子中放著一定數量的蘋果。你從左上角的格子開始, 每一步只能向下走或是向右走,每次走到一個格子上就把格子裡的蘋果收集起來, 這樣下去,你最多能收集到多少個蘋果。
解這個問題與解其它的DP問題幾乎沒有什麼兩樣。第一步找到問題的“狀態”, 第二步找到“狀態轉移方程”,然後基本上問題就解決了。
首先,我們要找到這 個問題中的“狀態”是什麼?我們必須注意到的一點是, 到達一個格子的方式最多隻有兩種:從左邊來的(除了第一列)和從上邊來的(除了第一行)。 因此為了求出到達當前格子後最多能收集到多少個蘋果, 我們就要先去考察那些能到達當前這個格子的格子,到達它們最多能收集到多少個蘋果。 (是不是有點繞,但這句話的本質其實是DP的關鍵:欲求問題的解,先要去求子問題的解)
經過上面的分析,很容易可以得出問題的狀態和狀態轉移方程。 狀態S[i][j]表示我們走到(i, j)這個格子時,最多能收集到多少個蘋果。那麼, 狀態轉移方程如下:
S[i][j]=A[i][j] + max(S[i-1][j], if i>0 ; S[i][j-1], if j>0)
其中i代表行,j代表列,下標均從0開始;A[i][j]代表格子(i, j)處的蘋果數量。
S[i][j]有兩種計算方式:1.對於每一行,從左向右計算,然後從上到下逐行處理;2. 對於每一列,從上到下計算,然後從左向右逐列處理。 這樣做的目的是為了在計算S[i][j]時,S[i-1][j]和S[i][j-1]都已經計算出來了。
參考網上的。
正確的程式碼:
import java.util.*;
public class Bonus {
public int getMost(int[][] board) {
int n=board.length;
int [][]dp=new int[n][n];
dp[0][0] = board[0][0];
//第一列,只能是從上面走下來的
for(int i=1;i<n;i++){
dp[i][0]=dp[i-1][0]+board[i][0];
}
//第一行,只能是從左邊走過來的
for(int i=1;i<n;i++){
dp[0][i]=dp[0][i-1]+board[0][i];
}
//其他行,既可能從上面來也可能從左邊來
for(int i=1;i<n;i++){
for(int j=1;j<n;j++){
dp[i][j]=board[i][j]+Math.max(dp[i-1][j], dp[i][j-1]);
}
}
return dp[n-1][n-1];
}
}
[程式設計題]拋小球
小東和三個朋友一起在樓上拋小球,他們站在樓房的不同層,假設小東站的樓層距離地面N米,球從他手裡自由落下,每次落地後反跳回上次下落高度的一半,並以此類推直到全部落到地面不跳,求4個小球一共經過了多少米?(數字都為整數)
給定四個整數A,B,C,D,請返回所求結果。
測試樣例:
100,90,80,70
返回:1020
坑人,不難,但是描述的有問題,取整不是每一步都取整,是最後取整,還是向上取整,題目表述不清晰
import java.util.*;
public class Balls {
public int calcDistance(int A, int B, int C, int D) {
// write code here
int instance = 0;
return (int)Math.ceil(fantan(A) + fantan(B) + fantan(C) + fantan(D));
}
public double fantan(double num) {
double instance = num;
while (num / 2 != 0) {
num = num / 2;
instance += num * 2;
}
return instance;
}
}
[程式設計題]小東分蘋果
果園裡有一堆蘋果,一共n頭(n大於1小於9)熊來分,第一頭為小東,它把蘋果均分n份後,多出了一個,它扔掉了這一個,拿走了自己的一份蘋果,接著第二頭熊重複這一過程,即先均分n份,扔掉一個然後拿走一份,以此類推直到最後一頭熊都是這樣(最後一頭熊扔掉後可以拿走0個,也算是n份均分)。問最初這堆蘋果最少有多少個。
給定一個整數n,表示熊的個數,返回最初的蘋果數。保證有解。
測試樣例:
2
返回:3
參考牛客網上的做法,從前向後推,這道題應該做出來的,靜下心來
import java.util.*;
public class Apples {
public int getInitial(int n) {
for(int i=n+1;;i++) {
int temp=i;
int bear=n;
while(bear>0) {
if(temp%n==1){
temp=temp-temp/n-1;
bear--;
}else {
break;
}
}
if(bear==0) {
return i;
}
}
}
}