1. 程式人生 > 其它 >寒假CS每日打卡 Feb.15th

寒假CS每日打卡 Feb.15th

技術標籤:2021寒假每日打卡演算法C++寒假學習LeetCodeAcwing


演算法部分

1.Acwing 入門組每日一題
題目:拼寫正確
給定一個非負整數 N,你的任務是計算 N 的所有數字的總和,並以英語輸出總和的每個數字。

輸入格式
共一行,包含一個整數 N。

輸出格式
共一行,用英語輸出總和的每個數字,單詞之間用空格隔開。

資料範圍
0≤N≤10100
輸入樣例:
12345
輸出樣例:
one five

題解:
  簡單的字串題目。

程式碼:

#include <iostream>
#include <string>
#include <algorithm>
using namespace std; string fun(int a){ string s; while(a){ s.push_back(a % 10 + '0'); a /= 10; } reverse(s.begin(), s.end()); if(s.empty()) s.push_back('0'); return s; } int main(){ string arr[10] = {"zero", "one", "two"
, "three", "four", "five", "six", "seven", "eight", "nine"}; string s; int sum = 0; cin >> s; for(char c : s) sum += c - '0'; s = fun(sum); for(char c : s) cout << arr[c -
'0'] << " "; return 0; }

2.Acwing 提高組每日一題
題目:機器人跳躍問題
機器人正在玩一個古老的基於DOS的遊戲。
遊戲中有N+1座建築——從0到N編號,從左到右排列。
編號為0的建築高度為0個單位,編號為 i 的建築高度為H(i)個單位。
起初,機器人在編號為0的建築處。
每一步,它跳到下一個(右邊)建築。
假設機器人在第k個建築,且它現在的能量值是E,下一步它將跳到第k+1個建築。
如果H(k+1)>E,那麼機器人就失去H(k+1)-E的能量值,否則它將得到E-H(k+1)的能量值。
遊戲目標是到達第N個建築,在這個過程中能量值不能為負數個單位。
現在的問題是機器人至少以多少能量值開始遊戲,才可以保證成功完成遊戲?

輸入格式
第一行輸入整數N。
第二行是N個空格分隔的整數,H(1),H(2),…,H(N)代表建築物的高度。

輸出格式
輸出一個整數,表示所需的最少單位的初始能量值上取整後的結果。

資料範圍
1≤N,H(i)≤105,

輸入樣例1:
5
3 4 3 2 4
輸出樣例1:
4
輸入樣例2:
3
4 4 4
輸出樣例2:
4
輸入樣例3:
3
1 6 4
輸出樣例3:
3

題解:
  利用二分法來暴力求解,當某一刻能量大於100000後肯定能跳到最後,此時應當跳出迴圈,因為高度最大值也就為100000。

程式碼:

#include <iostream>

using namespace std;

const int MAXN = 1e5 + 10;
int arr[MAXN], n;

bool check(int mid){
    for(int i = 0; i < n; i ++){
        mid += mid - arr[i];
        if(mid < 0)
            return false;
        if(mid > MAXN)
            return true;
    }
    return true;
}

int main(){
    cin >> n;
    for(int i = 0; i < n; i ++)
        cin >> arr[i];
    
    int le = 1, ri = MAXN, mid;
    while(le < ri){
        mid = le + ri >> 1;
        //合法就縮小初始能量
        if(check(mid))
            ri = mid;
        else
            le = mid + 1;
    }
    cout << ri << endl;
    return 0;
}

3.LeetCode 每日一題
題目:最大連續1的個數
給定一個二進位制陣列, 計算其中最大連續1的個數。

示例 1:
輸入: [1,1,0,1,1,1]
輸出: 3
解釋: 開頭的兩位和最後的三位都是連續1,所以最大連續1的個數是 3.

注意:
輸入的陣列只包含 0 和1。
輸入陣列的長度是正整數,且不超過 10,000。

題解:
  利用雙指標線性求解。

程式碼:

class Solution {
public:
    int findMaxConsecutiveOnes(vector<int>& nums) {
        int pre = 0, ans = 0;

        for(int i = 0; i < nums.size(); i ++){
        	//為 0
            if(!nums[i]){
            	//更新答案
                ans = max(ans, i - pre);
                //找到下一個1的位置
                while(i < nums.size() && !nums[i])
                    ++ i;
                //更新pre
                pre = i;
            }
        }
        ans = max(ans, (int)nums.size() - pre);
        return ans;
    }
};

4.力扣228周賽 – 一個圖中連通三元組的最小度數
題目:
給你一個無向圖,整數 n 表示圖中節點的數目,edges 陣列表示圖中的邊,其中 edges[i] = [ui, vi] ,表示 ui 和 vi 之間有一條無向邊。
一個 連通三元組 指的是 三個 節點組成的集合且這三個點之間 兩兩 有邊。
連通三元組的度數 是所有滿足此條件的邊的數目:一個頂點在三元組內,而另一個頂點不在三元組內。
請你返回所有連通三元組中度數的 最小值 ,如果圖中沒有連通三元組,那麼返回 -1 。

示例 1:
在這裡插入圖片描述
輸入:n = 6, edges = [[1,2],[1,3],[3,2],[4,1],[5,2],[3,6]]
輸出:3
解釋:只有一個三元組 [1,2,3] 。構成度數的邊在上圖中已被加粗。

示例 2:

在這裡插入圖片描述
輸入:n = 7, edges = [[1,3],[4,1],[4,3],[2,5],[5,6],[6,7],[7,5],[2,6]]
輸出:0
解釋:有 3 個三元組:

  1. [1,4,3],度數為 0 。
  2. [2,5,6],度數為 2 。
  3. [5,6,7],度數為 2 。

提示:
2 <= n <= 400
edges[i].length == 2
1 <= edges.length <= n * (n-1) / 2
1 <= ui, vi <= n
ui != vi
圖中沒有重複的邊。

題解:
  三層for迴圈遍歷所有的三元組來求解,純暴力,注意到提示中說到圖沒有重複的邊,可以將兩個數字雜湊到一個數字,以此來判斷兩點之間的邊是否存在。

程式碼:

bool cnt[200010];

class Solution {
public:
    int minTrioDegree(int n, vector<vector<int>>& edges) {
        int ans = INT_MAX;
        memset(cnt, 0, sizeof(cnt));
        vector<int> degree(n + 1, 0);

        for(auto &i : edges){
        	//保證邊的first一定大於second
            if(i[0] > i[1])
                swap(i[0], i[1]);
            //雜湊到一維,n最大為400,500已經能保證沒有衝突
            cnt[i[0] * 500 + i[1]] = true;
            //兩條邊的入讀 + 1
            degree[i[0]] ++;
            degree[i[1]] ++;
        }
		//3層for迴圈遍歷所有的三元組
        for(int i = 1; i <= n; i ++){
            for(int j = i + 1; j <= n; j ++){
                if(!cnt[i * 500 + j])
                    continue;
                for(int k = j + 1; k <= n; k ++){
                    if(cnt[i * 500 + k] && cnt[j * 500 + k])
                    	//-6 因為三元組內部有6個度
                        ans = min(ans, degree[i] + degree[j] + degree[k] - 6);
                }
            }
        }
        return ans == INT_MAX ? -1 : ans;
    }
};

書籍部分

演算法競賽.進階指南 0x61最小生成樹 ✔
LeetBook 硬核作業系統指南 計算機硬體介紹 ✔
LeetBook 硬核 Linux 攻略 Linux簡介 ✔


PS.