笔试强训week2

day1

Q1   难度⭐⭐

字符串中找出连续最长的数字串_牛客题霸_牛客网 (nowcoder.com)

题目
读入一个字符串str,输出字符串str中的连续最长的数字串

输入描述:个测试输入包含1个测试用例,一个字符串str,长度不超过255。

输出描述:在一行内输出str中里连续最长的数字串。

思路:

快慢指针记录更新最长区间

#include <iostream>
#include <string>
using namespace std;

string find(string s)
{
    string ans;
    int slow = 0;
    while(slow < s.size())
    {
        while(slow < s.size() && s[slow] < '0' || s[slow] > '9')
            slow ++;
        int fast = slow + 1;
        int n = 1;
        while(s[fast] >= '0' && s[fast] <= '9')
        {
            n ++;
            fast ++;
        }
        if(ans.size() < n)
            ans = s.substr(slow, n);
        slow = fast;
    }
    return ans;
}

int main() 
{
    string s;
    cin >> s;
    if(s.empty())
    {
        cout << "" << endl;
        return 0;
    }
    cout << find(s) << endl;

    return 0;
}

 Q2   难度⭐⭐⭐

岛屿数量_牛客题霸_牛客网 (nowcoder.com)

题目
给一个01矩阵,1代表是陆地,0代表海洋, 如果两个1相邻,那么这两个1属于同一个岛。我们只考虑上下左右为相邻。

岛屿: 相邻陆地可以组成一个岛屿(相邻:上下左右) 判断岛屿个数。

思路

从左上角开始遍历,碰见“岛屿”将结果+1并多源DFS将“岛屿”变“海洋”

#include <vector>
class Solution 
{
public:
    int ans = 0;

    vector<vector<int> > d = {{-1,0},{1,0},{0,-1},{0,1}};
    vector<int> find = {0,0,0,0};

    void dfs(int i, int j, vector<vector<char> >& grid)
    {
        if(i >= grid.size() || i < 0 || j >= grid[0].size() || j < 0 || grid[i][j] == '0')
        {
            return;
        }

        grid[i][j] = '0';

        for(int k = 0; k < d.size(); k++)
        {
            dfs(i + d[k][0], j + d[k][1], grid);
        }
    }

    int solve(vector<vector<char> >& grid) 
    {
        for(int i = 0; i < grid.size(); i ++)
            for(int j = 0; j <grid[0].size(); j ++)
            {
                if(grid[i][j] == '1')
                {
                    ans ++;
                    dfs(i, j, grid);
                }
            }
            
        return ans;
    }
};

Q3   难度⭐⭐⭐

A-拼三角_牛客小白月赛32 (nowcoder.com)

题目
给出6根棍子,能否在选出3根拼成一个三角形的同时剩下的3根也能组成一个三角形?

输入描述:首先在一行中给出一个 t,1\leq t\leq 10^{3},代表测试数据的组数,接下来t行,每行给出6个数字代表棍子长度,棍子长度为正且小于10^{9}

输出描述:在一行中输出 "Yes" or "No"

思路

每6个数判断一遍是否能33围成三角形(两边之和大于第三边)

全排列
先sort
再next_permutation

#include <iostream>
#include <algorithm>
using namespace std;

bool YES(int a, int b, int c)
{
    if(a + b > c && a + c > b && b + c > a)  return 1;
    else return 0;
}

int main() 
{
    int n;
    cin >> n;
    while(n--)
    {
        int s[6];
        for(int i = 0; i < 6; i++)
            cin >> s[i];
        sort(s, s + 6);
        bool find = 0;
        do
        {
            if(YES(s[0], s[1], s[2]) && YES(s[3], s[4], s[5]))
            {
                find = 1;
                break;
            }
        } while(next_permutation(s, s + 6));

        if(find != 0)  cout << "Yes" << endl;
        else  cout << "No" << endl;
    }

    return 0;
}

day2

Q1   难度⭐

求最小公倍数_牛客题霸_牛客网 (nowcoder.com)

题目
正整数A和正整数B 的最小公倍数是指 能被A和B整除的最小的正整数值,设计一个算法,求输入A和B的最小公倍数。

数据范围:1≤𝑎,𝑏≤100000

思路

while(c * a % b != 0)  c ++;
最小公倍数为 a * c;

#include <iostream>
using namespace std;

int main() 
{
    int a, b;
    long long c = 1;
    cin >> a >> b;
    while(c * a % b != 0)
        c ++;
    cout << a * c;

    return 0;
}

Q2   难度⭐

数组中的最长连续子序列_牛客题霸_牛客网 (nowcoder.com)

题目
给定无序数组arr,返回其中最长的连续序列的长度(要求值连续,位置可以不连续,例如 3,4,5,6为连续的自然数)

数据范围:1\leq n\leq 10^{5}1\leq val\leq 10^{8}

思路

先排序,再判断前后差值是否为1,并更新记录最长长度

#include <vector>
class Solution 
{
public:
    int MLS(vector<int>& arr) 
    {
        if(arr.size() == 1)  return 1;

        sort(arr.begin(),arr.end());
        int ans = 1;
        int tmp = 1;

        for(int i = 1; i < arr.size(); i++)
        {
            if(arr[i]-arr[i-1] == 1)
                tmp += 1;
            else if(arr[i] == arr[i-1])
                continue;
            else  
                tmp = 1;
            ans = max(ans, tmp);
        }
        
        return ans;
    }
};

Q3   难度⭐⭐

字母收集_牛客题霸_牛客网 (nowcoder.com)

题目
有一个 𝑛∗𝑚 的矩形方阵,每个格子上面写了一个小写字母。
小红站在矩形的左上角,她每次可以向右或者向下走,走到某个格子上就可以收集这个格子的字母。小红非常喜欢 "love" 这四个字母。她拿到一个 l 字母可以得 4 分,拿到一个 o 字母可以得 3 分,拿到一个 v 字母可以得 2 分,拿到一个 e 字母可以得 1 分。
她想知道,在最优的选择一条路径的情况下,她最多能获取多少分?

输入描述:1≤n,m≤500,接下来的 𝑛 行 每行一个长度为 𝑚 的、仅有小写字母构成的字符串,代表矩形方阵。

输出描述:小红最大可能的得分。

思路

dp(记录从右下角往左或上走,使其结果最大)

#include <iostream>
using namespace std;

char s[510][510];
int dp[510][510];

int main() 
{
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
        cin >> s[i] + 1;
        
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
        {
            if(s[i][j] == 'l') dp[i][j] = 4;
            if(s[i][j] == 'o') dp[i][j] = 3;
            if(s[i][j] == 'v') dp[i][j] = 2;
            if(s[i][j] == 'e') dp[i][j] = 1;
        }

    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            dp[i][j] = max(dp[i - 1][j] + dp[i][j], dp[i][j - 1] + dp[i][j]);
    cout << dp[n][m] <<endl;

    return 0;
}

day3

Q1   难度⭐

添加逗号_牛客题霸_牛客网 (nowcoder.com)

题目
对于一个较大的整数 N(1<=N<=2,000,000,000)比如 980364535,我们常常需要一位一位数这个数字是几位数,但是如果在这 个数字每三位加一个逗号,它会变得更加易于朗读。因此,这个数字加上逗号成如下的模样:980,364,535请写一个程序帮她完成这件事情

思路

翻转,再倒序输出(每3位数输出一次",")

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

int main() 
{
    string n;
    cin >> n;
    reverse(n.begin(), n.end());
    for(int i = n.size() - 1; i >= 0; i --)
    {
        if((i + 1) % 3 == 0 && i + 1 < n.size())
            cout << ",";
        cout << n[i];
    }
    return 0;
}

Q2   难度⭐

跳台阶_牛客题霸_牛客网 (nowcoder.com)

题目
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个 n 级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

数据范围:0≤𝑛≤40

要求:时间复杂度:𝑂(𝑛) ,空间复杂度: 𝑂(1)

输入描述:本题输入仅一行,即一个整数 n

输出描述:输出跳上 n 级台阶有多少种跳法

思路

最简单的dp

#include <iostream>
using namespace std;

int main() 
{
    int n;
    cin >> n;
    if(n < 3)
    {
        cout << n;
        return 0;
    }
    int a[41];
    a[1] = 1;
    a[2] = 2;
    for(int i=3;i<=n;i++)
        a[i]=a[i-1]+a[i-2];
    cout<<a[n];
    return 0; 
}

Q3   难度⭐⭐

扑克牌顺子_牛客题霸_牛客网 (nowcoder.com)

题目
现在有2副扑克牌,从扑克牌中随机五张扑克牌,我们需要来判断一下是不是顺子。
有如下规则:
1. A为1,J为11,Q为12,K为13,A不能视为14
2. 大、小王为 0,0可以看作任意牌
3. 如果给出的五张牌能组成顺子(即这五张牌是连续的)就输出true,否则就输出false。
4.数据保证每组5个数字,每组最多含有4个零,数组的数取值为 [0, 13]

输入描述:输入五张扑克牌的值

返回值描述:五张扑克牌能否组成顺子。

思路

记录0的个数,判断是否有重复的牌(非0),计算最大牌与最小牌的差值(非0)是否小于5

class Solution 
{
public:
    bool IsContinuous(vector<int>& numbers) 
    {
        sort(numbers.begin(), numbers.end());
        
        int king_nums = 0;
        int i = 0;
        while(numbers[i] == 0)
        {
            king_nums ++;
            i ++;
        }
        if(king_nums == 4) return true;

        int j = i;
        while(j < numbers.size())
        {
            if(numbers[j] == numbers[j - 1])
                return false;
            j ++;
        }

        return numbers.back() - numbers[i] < 5;
    }
};

day4

Q1   难度⭐⭐

最长回文子串_牛客题霸_牛客网 (nowcoder.com)

题目
对于长度为n的一个字符串A(仅包含数字,大小写英文字母),请设计一个高效算法,计算其中最长回文子串的长度。

数据范围: 1≤𝑛≤10001≤n≤1000

思路

快慢指针

class Solution 
{
public:
    int getLongestPalindrome(string A) 
    {
        int LongestPalindrome = 0;
        for(int i = 0; i < A.size(); i++)
        {
            int l = i;
            int r = i;
            while(r < A.size() - 1 && A[r] == A[r + 1])  r++;
            while (l <= r && r < A.size() && A[l] == A[r]) 
            {
                l --;
                r ++;
            }
            LongestPalindrome = max(LongestPalindrome, r - l - 1);
        }
        return LongestPalindrome;
    }
};

Q2   难度⭐⭐

买卖股票的最好时机(一)_牛客题霸_牛客网 (nowcoder.com)

题目
假设你有一个数组prices,长度为n,其中prices[i]是股票在第i天的价格,请根据这个价格数组,返回买卖股票能获得的最大收益

  1. 你可以买入一次股票和卖出一次股票,并非每天都可以买入或卖出一次,总共只能买入和卖出一次,且买入必须在卖出的前面的某一天
  2. 如果不能获取到任何利润,请返回0
  3. 假设买入卖出均无手续费

输入描述:第一行输入一个正整数 n 表示数组的长度
                  第二行输入 n 个正整数,表示股票在第 i 天的价格

输出描述:输出只买卖一次的最高收益

思路

每次输入记录当前最小值和与最小值的最大差值

#include <iostream>
#include <algorithm>
using namespace std;

int main() 
{
    int n;
    cin >> n;
    int ans = 0, min_price = 0x3f3f3f;
    int day_prices;
    for(int i = 0; i < n; i ++)
    {
        cin >> day_prices;
        ans = max(ans, day_prices - min_price);
        min_price = min(min_price, day_prices);
    }
    
    cout << ans << endl;
    return 0;
}

Q3   难度⭐⭐⭐⭐

[NOIP2002]过河卒 (nowcoder.com)

题目
如图,𝐴 点有一个过河卒,需要走到目标 𝐵 点。卒行走规则:可以向下、或者向右。同时在棋盘上的任一点有一个对方的马(如上图的 C𝐶 点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点。例如图中 𝐶 点上的马可以控制 9 个点(图中的 𝑃1,𝑃2…𝑃8 和 𝐶)。

卒不能通过对方马的控制点

棋盘用坐标表示,𝐴 点的坐标为 (0,0)、𝐵 点的坐标为 (𝑛,𝑚) ,马的位置 𝐶 点的坐标为 (𝑋,𝑌)(约定: 𝐶≠𝐴,同时 𝐶≠𝐵)。

现在要求你计算出卒从 𝐴 点能够到达 𝐵 点的路径的条数。

输入格式:共一行,包含 n,m,X,Y𝑛,𝑚,𝑋,𝑌。

输出格式:一个整数,表示路径条数。

数据范围:1≤𝑛,𝑚≤20,0≤𝑋≤𝑛,0≤Y≤m

思路

先bfs标记障碍物,再dp从原点到B

#include <iostream>
#include <algorithm>
using namespace std;

const int N = 400, M = 400;
typedef long long LL;

bool map[N][M];
LL dp[N][M];
bool st[N][M];
pair<int, int> q[M];

int dx[] = {0, -2, -2, -1, -1,  1,  1,  2,  2};
int dy[] = {0, -1,  1, -2,  2, -2,  2, -1,  1};
int ddx[] = {0, 1, 0}, ddy[] = {0, 0, 1};

int main() 
{
    int n, m, x, y;
    cin >> n >> m >> x >> y;
    n++, m++, x++, y++;

    map[x][y] = true;
    for(int i = 1; i <= 8; i ++)
    {
        int a = x + dx[i], b = y + dy[i];
        if(a >= 1 && a <= n && b >= 1 && b <= m)
            map[a][b] = true;
    }

    q[0] = {1, 1};
    dp[1][1] = 1;
    int hh = 0, tt = 0;
    while (hh <= tt) 
    {
        auto t = q[hh++];
        for(int i = 1; i <= 2; i++)
        {
            int a = t.first + ddx[i], b = t.second +ddy[i];
            if(a >= 1 && a <= n && b >= 1 && b <= m && !map[a][b])
            {
                dp[a][b] = dp[a - 1][b] + dp[a][b - 1];
                if(!st[a][b])
                    q[++ tt] = {a, b}, st[a][b] = true;
            }
        }
    }
    cout << dp[n][m] << endl;
    return 0;
}

day5

Q1   难度⭐⭐⭐

C-游游的水果大礼包_牛客周赛 Round 3 (nowcoder.com)

题目
游游有n个苹果,m个桃子。她可以把2个苹果和1个桃子组成价值a元的一号水果大礼包,也可以把1个苹果和2个桃子组成价值b元的二号水果大礼包。游游想知道,自己最多能组成多少价值总和的大礼包?

输入描述:四个正整数 n,m,a,b,用空格隔开。分别代表苹果的数量、桃子的数量、一号大礼包价值、二号大礼包价值。1\leq n,m,a,b\leq 10^6
输出描述:一个整数,代表大礼包的最大价值总和。

思路

计算x = n - i * 2,表示一号大礼包的数量。

计算y = m - i,表示二号大礼包的数量。

注意:数据范围超int,用long long

#include <iostream>
using namespace std;

typedef long long LL ;

int main() 
{
    LL n, m, a, b, ans;
    cin >> n >> m >> a >> b;
    if((n == m && n == 1 && m == 1) || n == 0 || m == 0) 
    {
        cout << "0" << endl;
        return 0;
    }
    else
    {
        for(int i = 0; 2 * i <= n && i <= m; i ++)
        {
            LL x = n - i * 2;
            LL y = m - i;
            LL j = min(x, y / 2);
            LL sum = i * a + j * b;
            ans = max(ans, sum);
        }
        cout << ans << endl;
        return 0;
    }
}

Q2   难度⭐

买卖股票的最好时机(二)_牛客题霸_牛客网 (nowcoder.com)

题目
假设你有一个数组prices,长度为n,其中prices[i]是某只股票在第i天的价格,请根据这个价格数组,返回买卖股票能获得的最大收益

  1. 你可以多次买卖该只股票,但是再次购买前必须卖出之前的股票
  2. 如果不能获取收益,请返回0
  3. 假设买入卖出均无手续费

输入描述:第一行输入一个正整数 n ,表示数组 prices 的长度
                  第二行输入 n 个正整数,表示数组中prices的值

输出描述:输出最大收益

思路

 每次输入记录当前当天与昨天的差值

#include <iostream>
using namespace std;

int main() 
{
    int n;
    cin >> n;
    int today_price = 0, yesterday_price = 0x3f3f3f;
    int ans = 0;
    for(int i = 0; i < n; i++)
    {
        cin >> today_price;
        if(today_price > yesterday_price)
            ans += today_price - yesterday_price;
        yesterday_price = today_price;
    }
    cout << ans << endl;
    return 0;
}

Q3   难度⭐⭐

倒置字符串_牛客题霸_牛客网 (nowcoder.com)

题目:
将一句话的单词进行倒置,标点不倒置。比如 I like beijing. 经过函数后变为:beijing. like I

思路:

读取输入 -> 分割字符串 -> 逆序输出字符串

stringstream在分割时只考虑空格字符

#include <iostream>
#include <vector>
#include <sstream>
using namespace std;

int main() 
{
    string line;
    getline(cin, line);
    stringstream ss(line);
    string word;
    vector<string> ans;

    while (ss >> word) //从ss中读取字符串,以空格为分隔符
        ans.push_back(word);

    for (int i = ans.size() - 1; i >= 0; i--) 
    {
        cout << ans[i];
        if (i > 0) 
            cout << ' ';
    }

    return 0;
}

day6

Q1   难度⭐

删除公共字符_牛客题霸_牛客网 (nowcoder.com)

题目
输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。例如,输入”They are students.”和”aeiou”,则删除之后的第一个字符串变成”Thy r stdnts.”

思路

遍历line2,在line1中find,若找到就erase

#include <iostream>
#include <string>
using namespace std;

int main() 
{
    string line1,line2;
    getline(cin, line1);
    cin >> line2;

    for(int i = 0; i < line2.size(); i ++)
    {
        while(line1.find(line2[i]) != string::npos)  //string::npos是string类的一个静态常量,表示字符串查找操作未找到目标字符时的返回值。
            line1.erase(line1.find(line2[i]), 1);
    }

    cout << line1 << endl;
    return 0;
}

Q2   难度⭐⭐

两个链表的第一个公共结点_牛客题霸_牛客网 (nowcoder.com)

题目
输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。

数据范围: 𝑛≤1000
要求:空间复杂度 𝑂(1),时间复杂度 𝑂(𝑛)

思路

class Solution 
{
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) 
	{
		if (pHead1 == NULL || pHead2 == NULL) return NULL;
   		struct ListNode *pA = pHead1, *pB = pHead2;
   		while (pA != pB) 
    	{
    	    pA = pA == NULL ? pHead2 : pA->next;
    	    pB = pB == NULL ? pHead1 : pB->next;
    	}

    	return pA;
    }
};

Q3   难度⭐

mari和shiny (nowcoder.com)

题目:
mari每天都非常shiny。她的目标是把正能量传达到世界的每个角落!
有一天,她得到了一个仅由小写字母组成的字符串。
她想知道,这个字符串有多少个"shy"的子序列?

输入描述:第一行一个正整数n,代表字符串的长度。(1≤n≤300000)
                  第二行为一个长度为n,仅由小写字母组成的字符串。
输出描述:一个正整数,代表子序列"shy"的数量。

思路:

统计当前h有多少个sh组合,后统计当前y有多少个shy组合

#include <iostream>
using namespace std;

int main() 
{
    int n;
    char ss;
    long long s = 0, h = 0, y = 0;
    cin >> n;
    while (n--) 
    {
        cin >> ss;
        if(ss == 's') s++;
        else if(ss == 'h') h += s;
        else if(ss == 'y') y += h;
    }

    cout << y << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

禊月初三

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值