寒假CS每日打卡 Feb.15th


算法部分

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简介 ✔

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值