網易機器學習算法工程師筆試編程題


1. 小易為了向他的父母表現他已經長大獨立了,他決定搬出去自己居住一段時間。一個人生活增加了許多花費: 小易每天必須吃一個水果並且需要每天支付x元的房屋租金。當前小易手中已經有f個水果和d元錢,小易也能去商店購買一些水果,商店每個水果售賣p元。小易為了表現他獨立生活的能力,希望能獨立生活的時間越長越好,小易希望你來幫他計算一下他最多能獨立生活多少天。 

輸入描述:
輸入包括一行,四個整數x, f, d, p(1 ≤ x,f,d,p ≤ 2 * 10^9),以空格分割
輸出描述:
輸出一個整數, 表示小易最多能獨立生活多少天。

 

輸入例子1:
3 5 100 10
輸出例子1:
11


C++代碼如下:
#include<iostream>
using namespace std;

int main(){
    int x, f, d, p;
    cin >> x >> f >> d >> p;
    int tmp1 = d / x;
    if(tmp1 <= f){
        cout<<tmp1;
        return 0;
    }
    d=d-(f*x);
    int tmp2=d/(x+p);
    cout<<f+tmp2;
    return 0;
}
 
        

 2. 小易將n個棋子擺放在一張無限大的棋盤上。第i個棋子放在第x[i]行y[i]列。同一個格子允許放置多個棋子。每一次操作小易可以把一個棋子拿起並將其移動到原格子的上、下、左、右的任意一個格子中。小易想知道要讓棋盤上出現有一個格子中至少有i(1 ≤ i ≤ n)個棋子所需要的最少操作次數.

輸入描述:
輸入包括三行,第一行一個整數n(1 ≤ n ≤ 50),表示棋子的個數
第二行為n個棋子的橫坐標x[i](1 ≤ x[i] ≤ 10^9)
第三行為n個棋子的縱坐標y[i](1 ≤ y[i] ≤ 10^9)
輸出描述:
輸出n個整數,第i個表示棋盤上有一個格子至少有i個棋子所需要的操作數,以空格分割。行末無空格

如樣例所示:
對於1個棋子: 不需要操作
對於2個棋子: 將前兩個棋子放在(1, 1)中
對於3個棋子: 將前三個棋子放在(2, 1)中
對於4個棋子: 將所有棋子都放在(3, 1)中
輸入例子1:
4
1 2 4 9
1 1 1 1
輸出例子1:
0 1 3 10
思路:對於一個k,我們找一個坐標(x, y)讓k個棋子距離這個坐標的曼哈頓距離之和最小。
            注意到x和y其實是獨立的,考慮枚舉棋盤上所有可能得坐標(x[i], y[j]),計算這個坐標到所有棋子的距離分別是多少,
            然后維護k個棋子對於這個坐標最小曼哈頓距離和即可。


C++代碼如下:
#include <bits/stdc++.h>

using namespace std;

const int inf = 1e9;

int main() {
    int n;
    cin >> n;
    vector<int> x;
    vector<int> y;
    int x_num;
    int y_num;
    for(int i = 0; i < n; i++){
        cin >> x_num;
        x.push_back(x_num);
    }
    for(int i = 0; i < n; i++){
        cin >> y_num;
        y.push_back(y_num);
    }
    
    vector<int> res(n, inf);//初始化為很大的數;
    
    //i表示存放最終的結果的下表;
    for(int i = 0; i < n; i++) {
        //j,k代表遍歷網格的坐標;
        for(int j = 0; j < n; j++) {
            for(int k = 0; k < n; k++) {
                vector<int> res2(n);
                //l代表每一個棋子所在的坐標;
                for(int l = 0; l < n; l++) {
                    res2[l] = abs(x[l] - x[j]) + abs(y[l] - y[k]);
                }
                sort(res2.begin(), res2.end());
                int res3 = 0;
                for(int l = 0; l < i + 1; l++) res3 += res2[l];
                res[i] = min(res[i], res3);
            }
        }
    }
    for(int i = 0; i < n; i++) {
        //輸出格式控制;
        i == 0 ? cout << res[i] : cout << " " << res[i];
    }
    return 0;
}
 
        

 3. 小易非常喜歡擁有以下性質的數列:
1、數列的長度為n
2、數列中的每個數都在1到k之間(包括1和k)
3、對於位置相鄰的兩個數A和B(A在B前),都滿足(A <= B)或(A mod B != 0)(滿足其一即可)
例如,當n = 4, k = 7
那么{1,7,7,2},它的長度是4,所有數字也在1到7范圍內,並且滿足第三條性質,所以小易是喜歡這個數列的
但是小易不喜歡{4,4,4,2}這個數列。小易給出n和k,希望你能幫他求出有多少個是他會喜歡的數列。 

輸入描述:
輸入包括兩個整數n和k(1 ≤ n ≤ 10, 1 ≤ k ≤ 10^5)
輸出描述:
輸出一個整數,即滿足要求的數列個數,因為答案可能很大,輸出對1,000,000,007取模的結果。
輸入例子1:
2 2
輸出例子1:
3

思路:想象一下,如果我們確定這個數列的第一個數是i,那么第二個數可以是1到k中除了是i的約數的任何數。
           於是我們定義dp[j][i]表示長度為i最后一個數是j的小易喜歡的數列的數量,然后挨着轉移即可。用動態規划的方法;


C++代碼如下:

#include <bits/stdc++.h>

using namespace std;

const int mod = 1e9 + 7;
const int maxn = 1e5 + 5;
int dp[maxn][15];
int n, k;
int main() {
    cin >> n >> k;
    dp[1][0] = 1;
    for(int i = 1; i <= n; i++) {
        int sum = 0;
        for(int j = 1; j <= k; j++) {
            sum += dp[j][i - 1];
            sum %= mod;
        }
        for(int j = 1; j <= k; j++) {
            int sum2 = 0;
            for(int z = j + j; z <= k; z += j) {
                sum2 += dp[z][i - 1];
                sum2 %= mod;
            }
            dp[j][i] = (sum - sum2 + mod) % mod;
        }
    }
    int ans = 0;
    for(int j = 1; j <= k; j++) {
        ans += dp[j][n];
        ans %= mod;
    }
    cout << ans << endl;
    return 0;
}
 
        

 總結:

第一個題目很簡單,但是沒有完全AC,一定要仔細思考,多嘗試案例,找到漏洞;

第二個題目,關於題目的意思沒有理解清楚,最初擔心復雜度的問題,到最后看到解法,其實就是用遍歷。所以先寫出一個可以運行的代碼,復雜度后面再說;

第三個題目是動態規划的問題,練得太少了,還沒想出思路來,對動態規划要更加熟悉。

 
        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM