拼多多和字節跳動、美團點評、京東、滴滴、攜程、網易互娛2020秋招筆試題覆盤

今年是什麼情況???這筆試題都是競賽題難度呀,菜雞表示很受傷。
多多少少做了一些大廠的筆試題,大佬勿噴,我覺得很多都是勸退筆試。

拼多多筆試題

求方差

給定n個整數,請找出其中3個數,滿足這3個數的組合是所有組合中方差最小的。
輸入描述:

共兩行,第一行一個整數n(2<n<3000)
第二行是n個整數
題目中出現的所有數字的絕對值小於100000

思路:先排個序,之後組成方差的3個數必然是連在一起的,逐個求,記錄最小值就好

#include<bits/stdc++.h>
using namespace std;
int a[3001]
int main() {
    int n;
    scanf("%d", &n);
    for(int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
}
    sort(a, a + n);
    double val, temp;
    //我之前因爲res初始化的比較小,導致了部分樣例是沒過得
    double res = 10000000;
    for(int i = 0; i < n - 2; i++) {
        val = (a[i] + a[i+1] + a[i+2]) / 3.0;
        temp = ((a[i] - val) * (a[i] - val) + (a[i+1] - val) * (a[i+1] - val) + (a[i+2] - val) * (a[i+2] - val)) / 3.0;
        res = min(res, temp);
}
    printf("%.2lf", res);
    return 0;
}

移動珍珠最小距離

多多雞有一串長度爲L的珍珠項鍊,上面有N顆珍珠,分佈在0到L-1這些位置上。現在多多雞想把所有的珍珠都移動到一起,並且想讓所有的珍珠移動的距離總和儘可能小。
所有的珍珠可以看作在一個環上,珍珠可以向相鄰的沒有珍珠的位置移動。
請輸出最優方案下的所有珍珠移動總和。

輸入描述:

共兩行,第一行兩個整數L、N(2 < N < L 100000)
第二行N個整數,表示每個珍珠所在的位置
題目保證所有珍珠的位置各不相同

分析:
滑動窗口問題,可以先考慮,如果問題不是成環的,而是線性的,該怎麼用滑動窗口解決

遞增序列總數

給定兩個正整數N和S,你需要找出所有的長度爲N的正整數數列,滿足單調遞增以及總和爲S的數列有多少個。

輸入描述:

共一行,兩個整數,N和S( 1 < N ,S < 100000)

輸出描述:

共一行,爲滿足條件的數列個數對1e9+7取模的結果

分析:
…也不會做
我們知道數列 1 到 n 求和爲 n * (n + 1) / 2
所以如果出現 n * (n + 1) / 2 > S那麼就是無解
結束後羣裏有大佬給了個解答:
用記憶化搜索求:
假設最小的數爲1, 那麼給N個數都加上初始值1,子問題成爲求長度爲N - 1,和爲S - N的遞增序列的個數。否則,依舊給N個數加上初始值,子問題成爲求長度爲N,和爲S-N 的遞增序列個數
f ( N , S) = f( N - 1, S - N) + f(N , S - N)

//
//  test.cpp
//  LeetCode
//
//  Created by huangyi on 2019/7/4.
//  Copyright © 2019 Leetcode. All rights reserved.
//
#include<bits/stdc++.h>
using namespace std;
int n, s;
const int mod = 1e9 + 7;
int cache[501][100001];
int count(int n, int s) {
    if(s <= 0) {
        return 0;
    }
    if(n * (n + 1) / 2 > s) {
        return 0;
    }
    if(n == 1) {
        return 1;
    }
    if(cache[n][s] != -1) {
        return cache[n][s];
    }
    cache[n][s] = count(n, s - n) + count(n - 1, s - n);
    if(cache[n][s] >= mod) {
        cache[n][s] -= mod;
    }
    return cache[n][s];
}
int main()
{
    scanf("%d %d", &n, &s);
    memset(cache, -1, sizeof(cache));
    int res = 0;
    res = count(n, s);
    printf("%d\n", res);
    return 0;
}

多多雞爬山

多多雞和同事們跑去大山裏露營,總共有N座山,所有的山按編號從小到大分佈在一條直線上。每座山的山頂上都有多多雞的同事。露營需要持續一個月,多多雞負責露營物資的運送和垃圾的回收,它需要每天開車去每座山的山頂一趟。這邊的路可以分爲三種,第一種從山底去到山頂的路,第二種從山頂到山底的路,第三種是山頂間的路。每座山都有對應的第一種和第二種路,某些山頂之間有第三種路相連。山頂間的路只有某些山頂之間纔有,並且只能從編號小的山開向編號大的山。

多多雞每天都需要從山底出發,去到所有的山頂。運送物資給同事們。因爲山路的特殊性,他可能需要來回山底山頂多次。現在多多雞想找出一個方案,可以保證每個山頂都去過至少一次的情況下,上山的次數儘可能少。

分析:
… 直接放棄,不會
結束後,某大佬說直接套 最小路徑覆蓋的板子就可以…
我當時…最小路徑覆蓋是什麼鬼…

字節跳動

起牀

當時第一題只過了0.8,最後交卷了也不知道咋回事,哪個地方沒過,結束後有人幫我指出來了
題目裏面提到了保證至少有一個鬧鐘可以讓牛牛及時到達教室,所以設置初始值的時候就要很當心,別漏了第一個鬧鐘、

#include<bits/stdc++.h>
using namespace std;
int main() {
    int n,hi[101] = {0}, mi[101] = {0}, x, a, b, t[101] = {0};
    scanf("%d", &n);
    for(int i = 0; i < n; i++) {
        scanf("%d %d", &hi[i], &mi[i]);
        t[i] = h[i] * 60 + mi[i];
}
    scanf("%d", &x);
    scanf("%d %d", &a, &b);
    int sum = a * 60 + b;
    int temp = sum - x;
    //我當時應該是這裏錯了
    int max = t[0];
    for(int i = 0; i < n; i++) {
        if(t[i] <= temp && t[i] >= max) {
            max = t[i];
}
}
    int h1 = max / 60;
    int m1 = max % 60;
    printf("%d %d\n", h1, m1);
    return 0;
}

解密

小明和安琪是好朋友,最近,他們的談話被一家偵察機構監控,所以他們想將他們的談話內容進行加密處理。於是,他們發明了一種新的加密方式,每條信息都被編譯成二進制數B(明文),其長度爲N。然後該信息被寫下k次,每次向右移動0,1,。。。K-1位。
然後對每一列進行異或操作,並且把最終所得結果記錄下來,記爲S密文。

輸入描述:

第一行兩個數N和K
第二行輸入一個二進制字符串S,長度爲N+K-1
1 <= N <= 1e6
1 <= K <= 1e6

輸出描述:

輸出明文B

示例:
輸入:

6 2
1110001

輸出:

101111
#include<bits/stdc++.h>
using namespace std;
int n, k, char s[2000010], ans[1000010];
int main() {
    scanf("%d %d", &n, &k);
    scanf("%s", s);
    ans[0] = s[0];
    int now = s[0] - '0';
    for(int i = 1; i < n; i++) {
        ans[i] = now ^ (s[i] - '0') + '0';
        now = now ^ (ans[i] - '0');
        if(i >= k - 1) {
            now = now ^ (ans[i-k+1] - '0');
} 
    ans[n] = '\0';
    printf("%s\n", ans);
    return 0;
}
}

發獎金

題目要求參考LeetCode135發糖果,基本一致


#include<bits/stdc++.h>
using namespace std;
int main() {
    int n,v;
    vector<int> nums;
    scanf("%d", &n);
    for(int i = 0; i < n; i++) {
        scanf("%d", &v);
        nums.push_back(v);
    }
    vector<int> price(n, 100);
    for(int i = 1; i < n; i++) {
        if(nums[i] > nums[i-1]) {
            price[i] = price[i-1] + 100;
        }
    }
    for(int i = n - 2; i >= 0; i--) {
        if(nums[i] > nums[i+1]) {
            price[i] = max(price[i], price[i+1] + 100);
        }
    }
    int res = 0;
    for(int i = 0; i < n; i++) {
        res += price[i];
    }
    printf("%d\n", res);
    return 0;
}

跑步

…不會,看不懂題目,不過大佬們說了是個樹形dp。
牛客上看到有大佬發代碼了,貼出來學習學習,我是看不懂了

作者:Nagichan
鏈接:https://www.nowcoder.com/discuss/221211
來源:牛客網

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 5;
const int MOD = 1e9 + 7;
int n;
LL ans[3], cnt[N][3], sum[N][3];
vector<int> G[N];
void dfs(int u, int fa) {
    //cout << u << ' ' << fa << endl;
    for(int i = 0; i < 3; i++) {
        cnt[u][i] = sum[u][i] = 0;
    }
    for(auto v : G[u]) {
        if(v == fa)
            continue;
        dfs(v, u);
        for(int x = 0; x < 3; x++) {
            for(int y = 0; y < 3; y++) {
                (ans[(x + y + 1) % 3] +=
                     cnt[v][y] * sum[u][x] % MOD
                     + cnt[u][x] * sum[v][y] % MOD
                     + cnt[u][x] * cnt[v][y] % MOD) %= MOD;
            }
        }
        for(int x = 0; x < 3; x++) {
            (cnt[u][(x + 1) % 3] += cnt[v][x]) %= MOD;
            (sum[u][(x + 1) % 3] += (sum[v][x] + cnt[v][x]) % MOD) %= MOD;
        }
    }
    cnt[u][0]++;
    for(int x = 0; x < 3; x++) {
        ans[x] += sum[u][x];
    }
}
 
int main() {
    scanf("%d", &n);
    for(int i = 0, u, v; i < n - 1; i++) {
        scanf("%d%d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1, -1);
    cout << ans[0] << ' ' << ans[1] << ' ' << ans[2] << endl;
    return 0;
}

美團筆試題

美團筆試題題型爲:40選擇+1問答+2編程

選擇題完全隨機,啥題型都有,點進去就看到微積分和線性代數等

問答題:
Restful調用和RPC調用什麼區別?如何設計一個RPC服務治理系統?Service mesh是爲了解決什麼問題?

編程題實際上考了兩道LeetCode原題:269和763,只不過換了下背景

快遞員分界

字符串 S 由大寫字母組成。我們要把這個字符串劃分爲儘可能多的片段,同一個字母只會出現在其中的一個片段。返回一個表示每個字符串片段的長度的列表。

輸入: S = "ABABCBACADEFEGDEHIJHKLIJ"
輸出: [9,7,8]
解釋:
劃分結果爲 "ABABCBACA", "DEFEGDE", "HIJHKLIJ"。
每個字母最多出現在一個片段中。

思路:
開一個數組記錄某個字母最後一次出現的下標i
從首字符開始遍歷字符串,找到首字符最後出現的位置,比較在該區間內字符在字符串中最後出現的位置是否超出區間,如果超出則將區間更新

#include<bits/stdc++.h>
using namespace std;

int main() {
    char a[1001];
    scanf("%s", a);
    int last[30];
    for(int i = 0; i < 26; i++) {
        last[i] = 0;
    }
    vector<int> v;
    for(int i = 0; i < strlen(a); i++) {
        last[a[i] - 'A'] = i;
    }
    for(int i = 0; i < strlen(a); i++) {
        int left = i, index = i, right = last[a[i] - 'A'];
        while(index <= right) {
            right = max(right, last[a[index++] - 'A']);
        }
        v.push_back(right - left + 1);
        i = right;
    }
    for(int i = 0; i < v.size(); i++) {
        if(i != v.size() - 1) {
            printf("%d ", v[i]);
        } else {
            printf("%d\n", v[i]);
        }
    }
    return 0;
}

火星文字典

題目描述:
已知一種新的火星文的單詞由英文字母組成,但是此火星文中的字母先後順序未知。給出一組非空的火星文單詞,且此組單詞已經按火星文字典序進行好了排序,請推斷出此火星文的字母先後順序。

輸入:
一行文本,爲一組按火星文字典序排序好的單詞(單詞兩端無引號),單詞之間通過空格隔開

輸出:
按火星文字母順序輸出出現過的字母,字母之間無其他字符,如果無法確定順序或者無合理的字母排序可能,請輸出“invalid”。

樣例輸入:
wrt wrf er ett rftt

樣例輸出:
wertf

思路:
按順序小的連接邊建圖,然後拓撲排序

#include<bits/stdc++.h>
using namespace std;

char s[100010], ss[1010][1010];

int G[30][30], indeg[30], have[30];

int main() {
    gets(s);
    for(int i = 0; i < 30; i++) {
        have[i] = 1;
        indeg[i] = 10;
    }
    int cnt = 0, len = 0, up = 0, time = 0;
    for(int i = 0; i <= strlen(s); i++) {
        if(s[i] == ' ' || i == strlen(s)) {
            ss[cnt++][len] = '\0';
            up = max(up, len);
            len = 0;
        } else {
            ss[cnt][len++] = s[i];
            time += have[s[i] - 'a'];
            have[s[i] - 'a'] = 0;
            indeg[s[i] - 'a'] = 0;
        }
    }
    for(int i = 0; i < 30; i++) {
        for(int j = 0; j < 30; j++) {
            G[i][j] = 0;
        }
    }
    for(int j = 0; j < up; j++) {
        int last = 0;
        for(int i = 1; i < cnt; i++) {
            if(j >= strlen(ss[i])) {
                continue;
            }
            bool flag = true;
            for(int k = 0; k < j; k++) 
                if( ss[last][k] != ss[i][k])
                    flag = false;
                if(flag && ss[last][j] != ss[i][j]) {
                    G[ss[last][j] - 'a'][ss[i][j] - 'a'] = 1;
                    indeg[ss[i][j] - 'a']++;      
                }
                last = i;
        }
    }
    string ans = "";
    queue<int> q;
    for(int i = 0; i < 30; i++) {
        if(indeg[i] == 0) {
            q.push(i);
        }
    }
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        ans += (char)u + 'a';
        for(int i = 0; i < 26; i++) {
            if(G[u][i] == 1) {
                indeg[i]--;
                if(indeg[i] == 0) {
                    q.push(i);
                }
            }
        }
    }
    if(ans.length() == time) {
            cout<<ans<<endl;
        } else {
            cout<<"invalid"<<endl;
        }
    return 0;
}

京東筆試題

京東題型是選擇+編程,也挺難的(個人覺得)
編程題有兩道

合唱隊

題目描述:
合唱隊的N名學生站成一排且從左到右編號爲1到N,其中編號爲i的學生身高爲H。現在將這些學生分成若干組(同一組的學生編號連續),並讓每組學生從左到右按身高從低到高進行排列,使得最後所有學生同樣滿足從左到右身高從低到高(中間位置可以等高),那麼最多可以將這些學生分成多少組?

輸入:
第一行包含一個整數N , 1 <= N <= 1e5
第二行包含N的空格隔開的整數Hi 到 HN ,1 <= Hi <= 1e9

輸出:
輸出能分成的最多組數

樣例輸入:

4
2 1 3 2

樣例輸出:

2

分析:
保證區間前半段的最大值小於等於後半段的最小值
可以開兩個輔助數組
leftMax[index]用於記錄[1, index]的最大值
rightMin[index]用於記錄[index, arrSize]的最小值
可以參考下LeetCode768


#include<bits/stdc++.h>
using namespace std;
int a[100001], leftMax[100001], rightMin[100001];
int main() {
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    int res = 1;
    leftMax[1] = a[1];
    for(int i = 2; i <= n; i++) {
        leftMax[i] = max(leftMax[i-1], a[i]);
    }
    rightMin[n] = a[n];
    for(int i = n - 1; i >= 1; i--) {
        rightMin[i] = min(rightMin[i+1], a[i]);
    }
    for(int i = 1; i < n; i++) {
        if(leftMax[i] <= rightMin[i+1]) {
            res++;
        }
    }

    printf("%d\n",res);
    return 0;
}

考場安排

輸入:
第一行兩個整數n和m,表示有n個男生和n個女生,有m個朋友關係
1 <= n <= 500 , 1 <= m <= 100000
接下來m行,每行有兩個整數,x和y,表示第x號男生和第y號女生是朋友,男生編號爲[1,n],女生編號爲[n+1, 2n]

輸出:
輸出第一行包含一個整數a,表示最少需要搬出教室的人數
輸出第二行有a個整數,即a個需要搬出教室的人的編號,要求人數最少,且字典序最小

樣例輸入:

2 2
1 3
1 4

樣例輸出:

1
1

分析:二分圖最小頂點覆蓋問題,匈牙利算法
…考場上交了個匈牙利寫的,只過了0.36???

滴滴筆試題

滴滴的筆試題個人覺得也是勸退題,(大佬勿噴)。
題型爲20選擇+2編程(編程題很難,ACM銀牌以上可以嘗試下)

算式轉移

在這裏插入圖片描述
分析:
這道題我的理解就是排序,碰到連續加、連續減、連續乘或者連續除的序列就進行排序,注意只能操作相鄰的兩個數。

移除序列

在這裏插入圖片描述

上述兩題的圖片來源網友。

另外提一下,移除序列這道題的出處應該是codefroces Sereja and Two Sequences

CF參考代碼

#include<bits/stdc++.h>
using namespace std;
int n, total, cost;
#define INF 0x3f3f3f
int a[50001];
int b[50001];
vector<int> v[50001];
int dp[50001][310];
int main() {
    memset(dp, INF, sizeof(dp));
    scanf("%d %d %d", &n, &total, &cost);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    for(int i = 1; i <= n; i++) {
        scanf("%d", &b[i]);
        v[b[i]].push_back(i);
    }
    int tot = total / cost;
    int res = 0;
    dp[0][0] = 0;
    for(int i = 1; i <= n; i++) {
        dp[i][0] = 0;
        for(int j = 1; j <= tot; j++) {
            dp[i][j] = dp[i-1][j];
            int temp = upper_bound(v[a[i]].begin(), v[a[i]].end(), dp[i][j-1]) - v[a[i]].begin();
            if(temp < v[a[i]].size()) {
                dp[i][j] = min(dp[i][j], v[a[i]][temp]);
            }
            if(j > res && j * cost + i + dp[i][j] <= total) {
                res = j;
            }
        }
    }
    printf("%d\n", res);
    return 0;
}

這道題好難理解呀。
看了題解後:考察的應該是dp+二分。需要優化
這道題看完我就想交卷了…打擾了,告辭

攜程筆試題

題型爲:20選擇+3編程

分隔鏈表

類似LeetCode86:可以參考:
https://blog.csdn.net/hy971216/article/details/82830998

大致意思就是給你一個單鏈表和一個整數m,要求你把鏈表裏小於等於m的結點放到前面,大於m的結點放到後面

參考代碼:

#include<bits/stdc++.h>
using namespace std;
//定義鏈表結點結構
struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};
//分隔鏈表 
ListNode* partition(ListNode* head, int x) {
        //定義兩個啞結點和兩個指針
        ListNode dummy1(0),dummy2(0);
        ListNode* p1 = &dummy1;
        ListNode* p2 = &dummy2;
        //定義輔助指針指向表頭
        ListNode* p = head;
        while(p) {
            //如果小於等於x,就接到p1後面
            if(p->val <= x) {
                p1->next = p;
                p1 = p1->next;
            } else {
            //反之接到p2後面
                p2->next = p;
                p2 = p2->next;
            }
            p = p->next;
        }
        p2->next = NULL;
        //讓p1指向p2
        p1->next = dummy2.next;
        return dummy1.next;
}
//構建單鏈表
void createList(ListNode* head, int n) {
    cin >> head->val;
    n--;
    for(int i = 0; i < n; i++) {
        //尾插法插入結點
        ListNode* p = new ListNode(0);
        cin >> p->val;
        p->next = nullptr;
        head->next = p;
        head = p;
    }
}
int main() {
    ListNode* head = new ListNode(0);
    head->next = nullptr;
    createList(head, 6);
    ListNode* res = partition(head, 3);
    while(res) {
        cout << res->val;
        cout << " ";
        res = res->next;
    }
    return 0;
}

反轉子串

參考代碼:

#include<bits/stdc++.h>
using namespace std;

int num[100000];
stack<int> a;
string resolve(string s) {
    string res = "";
    int len = s.size();
    if(len <= 2) {
        return res;
    }
    for(int i = 0; i < len; i++) {
        if(s[i] == '(') {
            a.push(i);
        } else if(s[i] == ')') {
            //這個判斷不能漏..不然只能過%71
            if(a.empty()) {
                return "";
            }
            num[i] = a.top();
            num[a.top()] = i;
            a.pop();
        }
    }
    int flag = 1;
    int i = 0;
    while(i < len) {
        if(s[i] == '(' || s[i] == ')') {
            i = num[i];
            flag = -flag;
        } else {
            res += s[i];
        }
        i += flag;
    }
    return res; 
}
int main() {
    string s;
    cin>>s;
    cout<< resolve(s) <<endl;
    return 0;
}

調度隊列

參考LeetCode 410分隔數組的最大值;
題目保證了沒有負數,如果有負數還要修改下思路
給定一個非負整數數組和一個整數 m,你需要將這個數組分成 m 個非空的連續子數組。設計一個算法使得這 m 個子數組各自和的最大值最小。

這題還是考察二分和貪心的思想,有人用dp做,但是dp的話數據量太大就過不了了

參考代碼:

#include<bits/stdc++.h>
using namespace std;
int n, m;
typedef long long ll;
int splitArray(vector<int>& nums, int m) {
    ll left = 0, right = 0;
    int n = nums.size();
    for(int i = 0; i < n; i++) {
        right += nums[i];
        if(left < nums[i]) {
            left = nums[i];
        }
    }
    ll res = right;
    while(left <= right) {
        ll mid = (left + right) >> 1;
        ll sum = 0;
        int cnt = 1;
        for(int i = 0; i < n; i++) {
            if(sum + nums[i] > mid) {
                cnt++;
                sum = nums[i];
            } else {
                sum += nums[i];
            }
        }
        if(cnt <= m) {
            res = min(res, mid);
            right = mid - 1;
        } else {
            left = mid + 1;
        }
    }
    return res;
}
int main() {
    scanf("%d %d", &m, &n);
    vector<int> nums;
    for(int i = 0; i < n; i++) {
        scanf("%d", &x);
        nums.push_back(x);
    }
    int res = splitArray(nums, m);
    printf("%d\n",res);
    return 0;
}

網易互娛

網易互娛我這批的筆試題其實不難,只是我比較菜而已。
第二題因爲平時練得太少,都不知道怎麼根據結點編號構建二叉樹了
第三題運氣好過了測試用例,實際提交只能過0…

迴文數

第一題就是判斷給定整數的二進制形式是不是一個迴文數(忽略前導0)
簡單的想法就是開一個數組保存這個數的二進制形式,然後判斷這個數組是否迴文即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int main() {
    int t;
    ll x;
    scanf("%d", &t);
    while(t--) {
    bool flag = false; 
    int a[111];
    int index = 0;
        scanf("%lld", &x);
        while(x != 0) {
            a[index++] = x % 2;
            x = x / 2;
        }
        for(int i = 0; i < index; i++) {
            if(a[i] != a[index - i - 1]) {
                flag = true;
                break;
            }
        }
        if(!flag) {
            printf("YES\n");
        } else {
            printf("NO\n");
        }
    }
    return 0;
}

遞增二叉樹

這題題目也是很好懂得,讓你判斷一顆二叉樹是不是一顆遞增二叉樹(就是上一層的結點值得和要小於等於下一層的結點值得和)
思路很簡單:就是根據結點值和編號構建二叉樹,然後層次遍歷二叉樹,遍歷完每一層坐下判斷即可。
…但是讓我寫代碼我就哭了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int size = 1001;
//樹結點結構
struct node {
    int val;
    node *left, *right;
    node(int v,node *l=NULL,node *r=NULL):val(v),left(l),right(r){}
};
//二叉樹層序遍歷
bool judge(node *root) {
    if(root == NULL) {
        return false;
    }
    queue<node* > q;
    q.push(root);
    int curSum = 0;
    int preSum = 0;
    while(!q.empty()) {
        curSum = 0;
        int len = q.size();
        for(int i = 0; i < len; i++) {
            node *temp = q.front();
            curSum += temp->val;
            q.pop();
            if(temp->left != NULL) {
                q.push(temp->left);
            }
            if(temp->right != NULL) {
                q.push(temp->right);
            }
            if(curSum < preSum) {
                return false;
            } 
            preSum = curSum;
        }
    }
    return true;
}
int main() {
    int t;
    scanf("%d", &t);
    while(t--) {
        int n;
        scanf("%d", &n);
        vector<node* > data;
        int *in = new int[n];
        //初始化
        for(int i = 0; i < n; i++) {
            node *temp = new node(-1);
            data.push_back(temp);
            in[i] = 0;
        }
        //構建二叉樹
        for(int i = 0; i < n; i++) {
            int v, l, r;
            scanf("%d %d %d", &v, &l, &r);
            in[l] = in[r] = 1;
            data[i]->val = v;
            if(l != -1) {
                data[i]->left = data[l];
            }
            if(r != -1) {
                data[i]->right = data[r];
            }
        }
        int r = 0;
        for(int i = 0; i < n; i++) {
            //找到根節點
            if(in[i] == 0) {
                r = i;
                break;
            }
        }
        if(judge(data[r])) {
            printf("YES\n");
        } else {
            printf("NO\n");
        }
    }
    return 0;
}

喝咖啡

這題主要是考察思維邏輯的嚴謹性,注意邊界問題等


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int main() {
    int t, k, m;
    cin >> t;
    while(t--) {
        cin >> k >> m;
        vector<int> data;
        data.push_back(1 - k - 1);
        for(int i = 0; i < m; i++) {
            int x;
            cin >> x;
            data.push_back(x);
        }
        data.push_back(30 + k + 1);
        int res = m;
        for(int i = 0; i < data.size() - 1; i++) {
            int diff = data[i + 1] - data[i] - 1;
            if(diff > k) {
                res += (diff - k) / (k + 1);
            }
        }
        cout << res << endl;
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章