算法编程

MT1 最大差值

链接

最大差值_牛客题霸_牛客网 (nowcoder.com)

描述

有一个长为 $n$ 的数组 $A$, 求满足 $0 \leq a \leq b<n$ 的 $A[b]-A[a]$ 的最大值。 给定数组 $A$ 及它的大小 $n$ ,请返回最大差值。 数据范围: $2<n \leq 2 * 10^5$ ,数组中的值满足 $0 \leq \mid$ val $\mid \leq 5 * 10^8$

示例

示例1

输入:

[5,1],2

返回值:

0

示例2

输入:

[5,6],2

返回值:

1

接口

题解

static const auto io_sync_off = []() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    return nullptr;
}
();

class Solution {
  public:
    int getDis(vector<int>& A, int n) {
        int d[n];
        d[0] = A[0];
        int r = 0;
        for (int i = 1; i < n; ++i) {
            if (A[i] < d[i - 1])
                d[i] = A[i];
            else d[i] = d[i - 1];
        }
        for (int i = 1; i < n; ++i) {
            if (A[i] - d[i] > r)
                r = A[i] - d[i];
        }
        return r;
    }
};

标签

贪心 动态规划 模拟

MT2 棋子翻转

链接

棋子翻转_牛客题霸_牛客网 (nowcoder.com)

描述

在 4x4 的棋盘上摆满了黑白棋子,黑白两色棋子的位置和数目随机,其中0代表白色,1代表黑色;左上角坐标为 (1,1) ,右下角坐标为 (4,4) 。 现在依次有一些翻转操作,要对以给定翻转坐标(x,y)(也即第x行第y列)为中心的上下左右四个棋子的颜色进行翻转。 给定两个数组 A 和 f ,分别代表 初始棋盘 和 哪些要进行翻转的位置(x,y) ,请返回经过所有翻转操作后的棋盘。

例如输入[[0,0,1,1],[1,0,1,0],[0,1,1,0],[0,0,1,0]],[[2,2],[3,3],[4,4]]时,初始键盘如下图所示:

img

对应的输出为[[0,1,1,1],[0,0,1,0],[0,1,1,0],[0,0,1,0]],如下图所示:

img

示例

示例1

输入:

[[0,0,1,1],[1,0,1,0],[0,1,1,0],[0,0,1,0]],[[2,2],[3,3],[4,4]]

返回值:

[[0,1,1,1],[0,0,1,0],[0,1,1,0],[0,0,1,0]]

接口

题解

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param A int整型vector<vector<>> 
     * @param f int整型vector<vector<>> 
     * @return int整型vector<vector<>>
     */
    set<vector<int>> set;

    void insert(vector<int> pos, int m, int n){
        if(pos[0] >= 1 && pos[0] <= m)
            if(pos[1] >= 1 && pos[1] <= n){
                if(set.find(pos) == set.end())
                    set.insert(pos);
                else
                    set.erase(pos);
            }

    }

    vector<vector<int> > flipChess(vector<vector<int> >& A, vector<vector<int> >& f) {
        // write code here
        int m = A.size();
        int n = A[0].size();
        for(auto& pos : f){
            vector<int> dm = {0, 0, 1, -1};
            vector<int> dn = {1, -1, 0, 0};
            for(int i = 0; i < 4; i++){
                vector<int> temp(pos);
                temp[0] += dm[i];
                temp[1] += dn[i];
                insert(temp, m, n);
            }
        }

        for(auto& pos : set){
            int x = pos[0] - 1;
            int y = pos[1] - 1;
            A[x][y] = 1 - A[x][y];
        }

        return A;
    }
};

标签

数组 模拟

MT3 拜访

链接

拜访_牛客题霸_牛客网 (nowcoder.com)

描述

现在有一个城市销售经理,需要从公司出发,去拜访市内的某位商家,已知他的位置以及商家的位置,但是由于城市道路交通的原因,他每次移动只能在左右中选择一个方向 或 在上下中选择一个方向,现在问他有多少种最短方案到达商家地址。

给定一个地图 CityMap 及它的 行长度 n 和 列长度 m ,其中1代表经理位置, 2 代表商家位置, -1 代表不能经过的地区, 0 代表可以经过的地区,请返回方案数,保证一定存在合法路径。保证矩阵的长宽都小于等于 10。

注意:需保证所有方案的距离都是最短的方案

数据范围: $2 \leq n, m \leq 10$

例如当输入为[[2,0,0,0],[0,-1,-1,0],[0,-1,1,0],[0,0,0,0]],4,4时,对应的4行4列CityMap如下图所示:

img

经理的位置在(2,2),商家的位置在(0,0),经分析,经理到达商家地址的最短方案有两种,分别为:

(2,2)->(2,3)->(1,3)->(0,3)->(0,2)->(0,1)->(0,0)

(2,2)->(3,2)->(3,1)->(3,0)->(2,0)->(1,0)->(0,0),所以对应的返回值为2

示例

示例1

输入:

[[0,1,0],[2,0,0]],2,3

返回值:

2

示例2

输入:

[[2,0,0,0],[0,-1,-1,0],[0,-1,1,0],[0,0,0,0]],4,4

返回值:

2

接口

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param CityMap int整型vector<vector<>> 
     * @param n int整型 
     * @param m int整型 
     * @return int整型
     */
    int countPath(vector<vector<int> >& CityMap, int n, int m) {
        // write code here
    }
};

题解

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param CityMap int整型vector<vector<>> 
     * @param n int整型 
     * @param m int整型 
     * @return int整型
     */
    int dx[4] = {1, 0, -1,  0};
    int dy[4] = {0, 1,  0, -1};
    int countPath(vector<vector<int> >& CityMap, int n, int m) {
        vector<int> d(n * m, 0x3f3f3f3f), f(n * m, 0);
        int src, dst;
        for(int i = 0; i < n ; i++){
            for(int j = 0; j < m; j++){
                if(CityMap[i][j] == 1){
                    src  = i * m + j;
                }else if(CityMap[i][j] == 2){
                    dst  = i * m + j;
                }
            }
        }

        queue<int> q;
        q.push(src);

        d[src] = 0, f[src] = 1;
        while(!q.empty()){
            int t = q.front(); q.pop();
            int x = t / m, y = t % m, nx, ny, nt;
            for(int i = 0; i < 4; i++){
                nx = x + dx[i], ny = y + dy[i];
                nt = nx * m + ny;
                if(nx >= 0 && nx < n && ny >= 0 && ny < m  && CityMap[nx][ny] != -1){
                    if(d[nt] >  d[t] + 1){
                        d[nt] =  d[t] + 1;
                        q.push(nt);      
                    }
                    if(d[nt] == d[t] + 1) f[nt] +=  f[t];
                }
            }
        }
        return  f[dst];
    }
};

标签

动态规划 广度优先搜索(BFS)

MT4 直方图内最大矩形

链接

直方图内最大矩形_牛客题霸_牛客网 (nowcoder.com)

描述

给定一个数组heights,长度为 $n$ ,height[i]是在第i点的高度,那么height[i]表示的直方图,能够形成的最大矩形是多少?

  1. 每个直方图宽度都为1

  2. 直方图都是相邻的

  3. 如果不能形成矩形,返回 0 即可

  4. 保证返回的结果不会超过 $2^{31}-1$

数据范围: $0<=$ heights $[i]<=10^4$ $0<=$ heights.length $<=10^5$ 如输入[3,4,7,8,1,2],那么如下:

img

示例

示例1

输入:

[3,4,7,8,1,2]

返回值:

14

示例2

输入:

[1,7,3,2,4,5,8,2,7]

返回值:

16

接口

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param heights int整型vector 
     * @return int整型
     */
    int largestRectangleArea(vector<int>& heights) {
        // write code here
    }
};

题解

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param heights int整型vector 
     * @return int整型
     */
    int largestRectangleArea(vector<int>& heights) {
        int max_area = 0;
        heights.push_back(0);
        stack<int> cache;
        for (int i = 0; i < heights.size(); ++i) {
            while (!cache.empty() && heights[cache.top()] >= heights[i]) {
                int cur_index = cache.top();
                cache.pop();
                int length = cache.empty() ? i : i - cache.top() - 1;
                int cur_area = heights[cur_index] * length;
                max_area = max(max_area, cur_area);
            }
            cache.push(i);
        }
        return max_area;
    }
};

标签

单调栈

MT5 字符串计数

链接

字符串计数_牛客题霸_牛客网 (nowcoder.com)

描述

求字典序在 s1 和 s2 之间的,长度在 len1 到 len2 的字符串的个数,结果 mod 1000007。 数据范围: $1 \leq \operatorname{len}(s 1), \operatorname{len}(s 2) \leq 50 , 1 \leq \operatorname{len} 1, \operatorname{len} 2 \leq 50$ 注意: 本题有多组输入

输入描述:

每组数据包涵s1(长度小于50),s2(长度小于50),len1(小于50),len2(大于len1,小于50)

输出描述:

输出答案。

示例

示例1

输入:

ab ce 1 2

输出:

56

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

//想明白了思路就很简单,代码也很少。
//求解大于str1的字符串个数以及大于str2的字符串个数,然后两者相减就能得到处于str1和str2之间的字符串个数
//对于求解长度len在[len1,len2]之间,且字典序大于某个字符串(str)的字符串个数:
//顺序遍历(i=0:n-1)str的每个字符str[i],则若一个字符串destr大于str,则有两种情况:
//(1)destr第i个字符大于str[i],则之后的字符无论是什么,destr都大于str
//(2)destr第i个字符等于str[i],则i++,并继续讨论后续字符
//最后如果len>strLen,需要考虑destr前strLen位和str完全一样,则剩余位置字符可以是任意字符。
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int getcount(char str[], int strLen, int len1, int len2){
    int count  = 0;
    for(int len = len1 ; len <= len2 ; len++){
        for(int i = 0 ;i < strLen && i < len; i++)
            count += (26 - (str[i] - 'a' + 1)) * pow(26 , strLen - i - 1 );
        if(len > strLen)
            count += pow(26 , len - strLen);
    }
    return count;
}
int main(){
    char str1[120];
    char str2[120];
    memset(str1,0,sizeof(str1));
    memset(str2,0,sizeof(str2));
    int len1, len2;
    while(cin >> str1 >> str2 >> len1 >> len2){
        int strlen1 = strlen(str1);
        int strlen2 = strlen(str2);
        int count1 = getcount(str1,strlen1,len1,len2);
        int count2 = getcount(str2,strlen2,len1,len2); 
        int count = count1 - count2 - 1;
        cout << count << endl;
    }
    return 0;
}

标签

动态规划 Java工程师 C++工程师 运维工程师 算法工程师 PHP工程师 美团 字符串 数学 进制转化 2016

MT6 平均年龄

链接

平均年龄_牛客题霸_牛客网 (nowcoder.com)

描述

已知某公司总人数为 $W$ ,平均年龄为 $Y$ 岁(每年 3 月末计算,同时每年 3 月初入职新人),假设每年离职率为 $x , x>0 & & x<1$, 每年保持所有员工 总数不变进行招聘,新员工平均年龄 21岁。 从今年 3 月末开始,请实现一个算法,可以计算出第 $\mathrm{N}$ 年后公司员工的平均年齡。(最后结果向上取整)。 数据范围: $1 \leq W \leq 1000 , 1 \leq Y \leq 30 , 0<x<1 , 1 \leq N \leq 100$

输入描述:

输入W Y x N

输出描述:

输出第N年后的平均年龄

示例

示例1

输入:

5 5 0.2 3

输出:

15

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

#include <stdio.h>
#include <math.h>
float getage(int w,float y,double x,int newage)
{
    return (1-x)*(y+1)+x*newage;
}
int main()
{
    int w,n;
    float x,y;
    while(scanf("%d %f %f %d",&w,&y,&x,&n)!=EOF){
        float answer;
        while(n>0)
        {
            answer=getage(w,y,x,21);
            y=answer;
            n--;
        }
        int a=ceil(answer);
        printf("%d\n",a);
    }
    return 0;
}

标签

Java工程师 C++工程师 运维工程师 算法工程师 PHP工程师 美团 数学 数组 思维 2016

MT7 字符编码

链接

字符编码_牛客题霸_牛客网 (nowcoder.com)

描述

请设计一个算法,给一个字符串进行二进制编码,使得编码后字符串的长度最短。 数字范围: 字符串长度满足 $1<n \leq 1000$ ,本题有多组输入

输入描述:

每组数据一行,为待编码的字符串。保证字符串长度小于等于1000。

输出描述:

一行输出最短的编码后长度。

示例

示例1

输入:

MT-TECH-TEAM

输出:

33

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

#include<iostream>
#include<string>
#include<queue>
#include<algorithm>
#include<functional>
using namespace std;
int main() {
    string s;
    while (cin >> s) {
        int n = s.length();
        sort(s.begin(), s.end());
        priority_queue<int, vector<int>, greater<int> > q;
        int i, j;
        for (i = 0; i < n; ) {
            for (j = i; j < n; ++j) {
                if (s[j] != s[i]){
                    q.push(j - i);
                    i = j;
                    break;
                }                
            }
            if (j == n) {
                q.push(j - i);
                break;
            }
        }
        int res = 0;
        while (q.size() > 1) {
            int a = q.top();
            q.pop();
            int b = q.top();
            q.pop();
            res += a + b;
            q.push(a + b);
        }
        cout << res << endl;
    }
    return 0;
}

标签

贪心 C++工程师 运维工程师 算法工程师 美团 字符串 golang工程师 iOS工程师 安卓工程师 前端工程师 测试工程师 PHP工程师 c#工程师 测试开发工程师 大数据开发工程师 Java工程师 2016

MT8 奇数位丢弃

链接

奇数位丢弃_牛客题霸_牛客网 (nowcoder.com)

描述

对于一个由 0..n 的所有数按升序组成的序列,我们要进行一些筛选,每次我们丢弃去当前所有数字中第奇数位个的数。重复这一过程直到最后剩下一个数。请求出最后剩下的数字。

数据范围: $1 \leq n \leq 1000$ ,本题有多组输入

输入描述:

每组数据一行一个数字,为题目中的n(n小于等于1000)。

输出描述:

一行输出最后剩下的数字。

示例

示例1

输入:

500

输出:

255

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

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

int main(){
    int n;
    while(cin>>n){
        int count=n+1;
        vector<int> vc(count);
        for(int i=0;i<count;i++){
            vc[i]=i;
        };
        while(count!=1){
            int i=0;
        for(;2*i+1<count;i++){
            vc[i]=vc[2*i+1];

            };
            count=i;

        };
        cout<<vc[0]<<endl;

    };
};

标签

链表 C++工程师 运维工程师 算法工程师 美团 数组 模拟 golang工程师 iOS工程师 安卓工程师 前端工程师 测试工程师 PHP工程师 c#工程师 测试开发工程师 大数据开发工程师 Java工程师 2016

MT9 二维数组打印

链接

二维数组打印_牛客题霸_牛客网 (nowcoder.com)

描述

有一个二维数组 (n*n) ,写程序实现从右上角到左下角沿主对角线方向打印。(注:主对角线方向为从左上角指向右下角这一斜线的方向)

给定一个二位数组 arr 及题目中的参数 n ,请返回结果数组。

数据范围: $1 \leq n \leq 300$

示例

示例1

输入:

[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]],4

返回值:

[4,3,8,2,7,12,1,6,11,16,5,10,15,9,14,13]

接口

class Printer {
public:
    vector<int> arrayPrint(vector<vector<int> > arr, int n) {
        // write code here
    }
};

题解

class Printer {
public:
    vector<int> arrayPrint(vector<vector<int> > arr, int n) {
        // write code here

    vector<int>res;
    //从右上角依次打印直到正对角线
    for(int i=n-1;i>=0;i--)
    {
      int x=0;
      int y=i;
      while(x<n && y<n)
      {
         res.push_back(arr[x++][y++]);  
      } 
    }
  //从正对角线依次打印
    for(int i=1;i<n;i++)
    {
       int x=i;
       int y=0;
       while(x<n && y<n)
       {
         res.push_back(arr[x++][y++]);  
       } 
    }
    return res;
    }
};

标签

数组 C++工程师 运维工程师 算法工程师 美团 模拟 golang工程师 iOS工程师 安卓工程师 前端工程师 测试工程师 PHP工程师 c#工程师 测试开发工程师 大数据开发工程师 Java工程师 2016

MT10 股票交易日

链接

股票交易日_牛客题霸_牛客网 (nowcoder.com)

描述

在股市的交易日中,假设最多可进行两次买卖(即买和卖的次数均小于等于 2 ),规则是必须一笔成交后进行另一笔(即买-卖-买-卖的顺序进行)。给出一天中的股票变化序列,请写一个程序计算一天可以获得的最大收益。请采用时间复杂度低的方法实现。

给定价格序列 prices 及它的长度 n ,请返回最大收益。

数据范围: $1 \leq n \leq 500 , 1 \leq$ prices $_i \leq 1000$

示例

示例1

输入:

[10,22,5,75,65,80],6

返回值:

87

接口

class Stock {
public:
    int maxProfit(vector<int> prices, int n) {
        // write code here
    }
};

题解

class Stock {
public:
    int maxProfit(vector<int> prices, int n) {
        // write code here
        int sell1 = 0 ,sell2 = 0;
        int buy1 = -prices[0],buy2 = -prices[0];
        for(int i=1;i<n;i++) {
            buy1 = max(buy1,-prices[i]);
            sell1 = max(sell1,buy1+prices[i]);
            buy2 = max(buy2,sell1 - prices[i]);
            sell2 = max(sell2,buy2 + prices[i]);
        }
        return sell2;
    }
};

标签

动态规划 C++工程师 运维工程师 算法工程师 美团 穷举 golang工程师 iOS工程师 安卓工程师 前端工程师 测试工程师 PHP工程师 c#工程师 测试开发工程师 大数据开发工程师 Java工程师 2016

MT11 丢失的三个数

链接

丢失的三个数_牛客题霸_牛客网 (nowcoder.com)

描述

现在有一个数组,其值为从 1 到 10000 的连续增长的数字。出于某次偶然操作,导致这个数组中丢失了某三个元素,同时顺序被打乱,现在需要你用最快的方法找出丢失的这三个元素,并且将这三个元素根据从小到大重新拼接为一个新数字,计算其除以 7 的余数。 例:丢失的元素为336 ,10 ,8435 ,得到的新数字为 103368435 ,除以七的余数为 2 。

输入描述:

输入数据为一行,包含9997个数字,空格隔开。

输出描述:

输出为一行,包含一个数字。

示例

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

#include<string>
#include<algorithm>
#include<vector>
#include<iostream>
#include<sstream>

using namespace::std;

int a[10001]={0};
int main()
{
    int i,j;
    int x;
    for(i=0;i<9997;i++)
    {
        scanf("%d",&x);
        a[x]=1;
    }
    string res=" ",s;
    long long sum=0;
    for(j=0;j<10000;j++)
    {
        if(a[j]==0)
        {
        stringstream ss;
        ss<<j;
            ss>>s;
            res+=s;
        }
    }
    stringstream ss;
    ss<<res;
    ss>>sum;
    printf("%d",sum%7);
}

标签

哈希

MT12 网格走法数目

链接

网格走法数目_牛客题霸_牛客网 (nowcoder.com)

描述

有一个 X*Y 的网格,小团要在此网格上从左上角到右下角,只能走格点(也即格子的顶点)且只能向右或向下走。请设计一个算法,计算小团有多少种走法。给定两个正整数 int x , int y ,请返回小团的走法数目。

数据范围: $1 \leq x, y \leq 10$

输入描述:

输入包括一行,逗号隔开的两个正整数x和y,取值范围[1,10]。

输出描述:

输出包括一行,为走法的数目。

示例

示例1

输入:

3 2

输出:

10

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

#include<iostream>
using namespace std;
/*
把网格看做二维坐标,向下为正,向右为正:
设f(m,n)代表从坐标(0,0)到坐标(m,n)的移动方法,则
f(m,n)=f(m-1,n)+f(m,n-1)
开始为f(0,0)=0,f(0,1)=1,f(1,0)=1
进行递归运算,退出条件就是m,n至少有个为0,否则就要继续递归运算。
*/
int get_ways(int x,int y){
    //if(x==0 &&y==0) return 0;
    if(x==1 &&y==0) return 1;
    if(x==0 &&y==1) return 1;
    if (x==0) return get_ways(x, y-1);
    if (y==0) return get_ways(x-1, y);
    else     
        return get_ways(x-1,y)+get_ways(x,y-1);
}

int main(){
    int X,Y;
    cin>>X>>Y;
    cout<<get_ways(X,Y);
    return 0;
}

标签

动态规划 基础数学

MT13 拼凑面额

链接

拼凑面额_牛客题霸_牛客网 (nowcoder.com)

描述

给你六种面额 1、5、10、20、50、100 元的纸币,假设每种币值的数量都足够多,编写程序求组成 n 元的不同组合的个数。

数据范围: $0 \leq n \leq 10000$ ,保证 $\mathrm{n}$ 是整数

输入描述:

输入为一个数字N,即需要拼凑的面额

输出描述:

输出也是一个数字,为组成N的组合个数。

示例

示例1

输入:

5

输出:

2

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解


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

int main()
{
    int N;
    char a[6]={1,5,10,20,50,100};
    cin>>N;
    vector<long> d(N+1,0);
    d[0]=1;
    for(int i=0;i<6;i++)
        for(int j=1;j<=N;j++)
            if(j>=a[i])
                d[j]=d[j]+d[j-a[i]];

    cout<<d[N]<<endl;

    return 0;
}

标签

动态规划

MT14 整数加法

链接

整数加法_牛客题霸_牛客网 (nowcoder.com)

描述

请设计一个算法能够完成两个用字符串存储的整数进行相加操作,对非法的输入则返回 error

数据范围: 字符串长度满足 $1 \leq n \leq 100$

输入描述:

输入为一行,包含两个字符串。

输出描述:

输出为一行。合法情况输出相加结果,非法情况输出error

示例

示例1

输入:

123 123
abd 123

输出:

246
error

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

#include<string>
#include<iostream>

using namespace std;

bool IsLegal(string & str)
{   
    if(str.empty())
        return false;
    for(int i = 0; i < str.size();++i)
    {
        if(str[i] >= '0' && str[i] <= '9')
            continue;
        else
            return false;
    }
    return true;
}

string Plus(string l_str,string r_str)
{
    if(!IsLegal(l_str) || !IsLegal(r_str))
        return "error\n";
    else
    {  
        //将长度小的放到右边
       if(l_str.size() < r_str.size())
       {
           string tmp = r_str;
           r_str = l_str;
           l_str = tmp;
       }
       int difference_size = l_str.size() - r_str.size();
       r_str.insert(r_str.begin(),difference_size,'0');//补齐0
       int carry = 0;
       string res_str(l_str.size()+1,'0');
       for(int i = l_str.size()-1;i >= 0;--i)
       {
           res_str[res_str.size()-1 -(l_str.size()-1 - i)] = ((r_str[i] - '0') + (l_str[i] - '0') + carry) % 10 + '0';
           carry = ((r_str[i] - '0') + (l_str[i] - '0') + carry ) / 10;
       }
       if(carry == 1)
           res_str[0] = '1';
       else
           res_str.erase(res_str.begin());
       return res_str;
    }
}

int main()
{
    string l_str;
    string r_str;
    while(std::cin >> l_str >> r_str)
        std::cout << Plus(l_str,r_str);
    return 0;
}

标签

数组

MT15 病毒传播

链接

病毒传播_牛客题霸_牛客网 (nowcoder.com)

描述

给出一个图 G(V,E) ,图上有 n 个点,m 条边,所有的边都是无向边。

最开始,也就是第 0 天的时候,这 n 个点中有一个点 v 感染了病毒,之后的每一天,凡是感染病毒的点都会向它的邻居点传播病毒。经过了 t 天之后,得到了感染病毒的点集 S 。要求找出第 0 天感染病毒的点 v 。如果 v 有很多不同的答案,把它们都找出来。

数据范围: $1 \leq n, m \leq 1000 , 1 \leq k \leq n , 1 \leq t \leq 10^9$

输入描述:

第一行两个数n,m,接下来有m行,每行两个数u,v,表示点u,v之间有一条无向边。接下来一行两个数k,t,其中k表示集合S的大小。最后一行k个数,集合S中的元素。输入的图可能有自环和重边,输入保证S中的数互不相同。

输出描述:

输出一行,如果不存在这样的v,输出-1。 否则输出所有可能的v,按照从小到大的顺序输出,数字之间用空格隔开,不要在行末输出多余的空格。

示例

示例1

输入:

4 3
3 2
1 2
1 4
3 2
4 2 1

输出:

4

说明:

第0天,第1天,第2天感染病毒的点如图

img

img

img

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

#include <bits/stdc++.h>
using namespace std;
bool ans[1005]; //感染了病毒的点标记为  1 没感染为 0
int temp[1005]; // bfs 过程中每个点最早被传染的时间    为  0说明没被传染
vector<int> vec[1005];//用邻接表表示的边集
queue<int> q; // bfs 中用到的队列
int n, t;
bool ok(int x) {//用 bfs 跑出以  x 为起点    传播  t 天的结果比较和实际结果是否相同
    for (int i = 1; i <= n; i++) temp[i] = 0;
    while (!q.empty()) q.pop();
    //以上是预处理
    temp[x] = 1;
    q.push(x);
    int now;
    while (!q.empty()) {
        now = q.front();
        q.pop();
        if (temp[now] > t) break;
        for (int i = 0; i < vec[now].size(); i++) {
            if (temp[vec[now][i]] == 0) {
                temp[vec[now][i]] = temp[now] + 1;
                q.push(vec[now][i]);
            }
        }
    }
    //以上是 bfs 可以保证复杂度  o(n)
    for (int i = 1; i <= n; i++) {
        if (ans[i] == 0 && temp[i] != 0) return 0;
        if (ans[i] != 0 && temp[i] == 0) return 0;
    }
    //以上是验证是否符合给出的点集
    return 1;
}
int main() {
  int m, u, v, num = 0;
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; i++) {
    scanf("%d%d", &u, &v);
    vec[u].push_back(v);
    vec[v].push_back(u);
  }
  //以上是建图
  int s, k;
  scanf("%d%d", &k, &t);
  for (int i = 1; i <= k; i++) {
    scanf("%d", &s);
    ans[s] = 1;
  }
  //标记被感染的点
  for (int i = 1; i <= n; i++) {
    if (ok(i)){ //输出符合结果的点
      if (num > 0) printf(" "); //防止行末空格
      num++;
      printf("%d", i);
    }
  }
  if (num == 0) //无解
    printf("-1");
  printf("\n");
  return 0;
}

标签

图 搜索

MT16 公交车

链接

公交车_牛客题霸_牛客网 (nowcoder.com)

描述

一座城市有 $n$ 个公交站台,站点从 1 到 $n$ 编号,和 $m$ 班公交车,公交车从 1 到 $m$ 编号,乘坐每班公交车只需花费 1 元钱,第 $i$ 班公交车一共经过 $t_i$ 个站点,分别为站点 $a_{i, 1}$ , $a_{i, 2} , \ldots , a_{i, t i}$,小明 可以乘坐第 $\mathrm{i}$ 班公交车从这 $t_i$ 个站台中的任意一个到达任意一个站点,如一班公交车经过站点 $1 , 2 , 3$ ,那么小明花费 1 元钱就可以从 1 到 2 ,从 1 到 3 ,从到 1 ,从 3 到 1 ,从到 2 。 小明想从 1 号站台到 $n$ 号站台,问他最少花费多少钱。

数据范围: $2 \leq n \leq 10^5 , 1 \leq m \leq 10^5 , 2 \leq t_i \leq n , 2 \leq n_i \times \sum_{i=1}^m t_i \leq 10^5$

输入描述:

第一行两个数 n , m。 接下来 m 行,依次描述公交车经过的站点,第 i 行开头一个数 t_i ,表示第 i 班公交车经过的站点数,接下来的 t_i 个数,依次表示这 t_i 个站点。

输出描述:

输出一个数,从 1 号站点到 n 号站点的最小代价,如果不能达到则输出 -1。

示例

示例1

输入:

5 3
3 1 2 3
3 3 4 2
3 3 5 4

输出:

2

说明:

先坐第一班公交车从 1 号到 3 号站点,再坐第三班公交车从 3 号站点到 5 号站点。

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

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

int main() {
  int n = 0;// 站点数
  int m = 0;// 公交车数
  scanf("%d%d", &n, &m);
  int nums = n+m+2; // 图的节点数
  vector<int> vec[nums]; // 从1开始
  // 建图同一辆公交车通过的点建一条边到这辆公交车的抽象点,再从抽象点建一条边到这些点
  for (int i = 1; i <= m; i++) {
    int t = 0;
    scanf("%d", &t); // 公交车数经过站点数
    for (int j = 1; j <= t; j++) {
      int a = 0;
      scanf("%d", &a); // 公交车数经过站点
      vec[a].push_back(i+n); // 同一站点经过的公交车
      vec[i+n].push_back(a); // 同一辆公交车通过的站点
    }
  }
  queue<int> q;              // 定义队列
  int visited[nums];           // 定义标记顶点是否已访问
  fill_n(visited,nums,-1);   // 初始化为未访问
  visited[1] = 0;            // 标记v已经访问
  q.push(1);                 // 入队v
  while (!q.empty()) {       // 队列非空
    int now = q.front();     // 取出队首元素
    q.pop();                 // 队首元素出队
    for (int i = 0; i < vec[now].size(); i++) { // 遍历v的邻接点
      int post = vec[now][i];// 取出邻接点
      if (-1 == visited[post]) {  // 判断邻接点是否访问
        visited[post] = visited[now]+1;// 标记邻接点已访问
        q.push(post);        // 邻接点入队
      }
    }
  } 
  if(-1 == visited[n]) printf("-1\n");
  else printf("%d\n",visited[n]/2);
  return 0;
}

标签

图 动态规划

MT17 共享单车

链接

共享单车_牛客题霸_牛客网 (nowcoder.com)

描述

给出一张图,图上有 $n$ 个节点,从 1 到 $n$ 编号,和 $m$ 条边,每条边有一个权重,表示小明走路通过这条边的时间,所有边都是无向的。 小明从 1 号节点出发,他要去 $n$ 号节点,他想用的总时间屈可能的短。小明有共享单车 APP,图上有些节点有共享单车,当他到达一个有车节点后,他就可以一直骑车,如果一条边走路通过 的时间是 $t$ ,那么骑车通过的时间就是 $t / 2$ ,这里的除法是向下取整,如 $t=1$ 时 $t / 2=0 , t=2$ 时, $t / 2=1$ 。 小明可以先走到一个节点取车再骑车过去,也可以直接走过去,问他在最优策略下,需要多少时间从 1 到 $n$ 。

数据范围: $1 \leq n, m \leq 10^5, 1 \leq u, v \leq n , 1 \leq w \leq 10^9 , 0 \leq k \leq n$

输入描述:

第一行两个数 n,m ,接下来有 m 行,每行三个数 u,v,w ,表示 u 和 v 之间有一条边权为 w 的无向边 接下来一个数 k ,表示有 k 个节点有车,最后输入 k 行,表示有车节点的编号 输入的图中可能有自环和重边

输出描述:

输出一个数,从 1 到 n 的最少所需的时间,如果 1 和 n 不连通,输出 -1

示例

示例1

输入:

4 3
1 3 1
1 2 3
2 4 4
1
3

输出:

4

说明:

小明走过去拿到车,然后骑车去目的地,路线入图:

img

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

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

struct Edge{
    int v, w;
};

struct P{
    int id;
    long s;
    bool flag;
};

struct cmp{
    bool operator()(const P &p1, const P &p2)const{
        return p1.s > p2.s;
    }
};

long vis[100003][2];
bool mp[100003] = {false};

int main(){
    memset(vis, 0x3f3f, sizeof(vis));
    memset(mp, false, sizeof(mp));
    int n, m, u, v, w, k;
    long t;
    scanf("%d%d", &n, &m);
    vector<Edge> G[n+1];
    for(int i=0;i<m;i++){
        scanf("%d%d%d", &u, &v, &w);
        G[u].push_back({v, w});
        G[v].push_back({u, w});
    }
    scanf("%d", &k);
    while(k--){
        scanf("%d", &u);
        mp[u] = true;
    }
    priority_queue<P, vector<P>, cmp> q;
    q.push({1, 0, mp[1]});
    vis[1][mp[1]] = 0;
    while(!q.empty()){
        P p = q.top();
        q.pop();
        if(p.id == n){
            printf("%ld\n", p.s);
            return 0;
        }
        for(auto &e: G[p.id]){
            if(p.flag)
                t = p.s + e.w/2;
            else
                t = p.s + e.w;
            bool flag = p.flag | mp[e.v];
            if(t < vis[e.v][flag]){
                vis[e.v][flag] = t;
                q.push({e.v, t, flag});
            }
        }
    }
    printf("-1\n");
    return 0;
}

标签

图 搜索

MT18 重要节点

链接

重要节点_牛客题霸_牛客网 (nowcoder.com)

描述

给出一张有向图 $G(V, E)$ ,所有的边都是有向边,对于图上的一个点 $v$ ,从 $v$ 出发可以到达的点的集合记为 $S_v$ ,特别地, $v \in S_v$ ,再定义一个点的集合 $T_v:$ 从 $T_v$ 中的任意一 个点出发,可以到达点 $\mathrm{v}$ ,特别地, $\mathrm{v} \in \mathrm{T}{\mathrm{v}}$ 简而言之, $\mathrm{S}{\mathrm{v}}$ 是 $\mathrm{v}$ 能到的点的集合,而 $\mathrm{T}_{\mathrm{v}}$ 是能到 $v$ 的点的集合。 对于一个点 $v$ ,如果 $T_v$ 中的点数严格大于 $S_v$ 中的点数,那么 $v$ 就是一个重要节点,输入一张图,输出图中重要节点的个数

数据范围: $1 \leq n, m \leq 1000 , 1 \leq u, v \leq n$

输入描述:

第一行输入两个数 n,m ,分别表示点数和边数。 接下来 m 行,每行两个数 u , v 。表示一条从 u 到 v 的有向边,输入中可能存在重边和自环。

输出描述:

输出一个数,重要节点的个数

示例

示例1

输入:

4 3
2 1
3 1
1 4

输出:

2

说明:

样例解释:重要节点是1,4。 

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

#include<bits/stdc++.h>

using namespace std;

int main() {
    int n, m, u, v, res;
    cin >> n >> m;
    vector<int> Graph[n + 1];
    vector<int> arrive(n + 1, 0);
    int visited[n + 1];
    for(int i = 0; i < m; ++i) {
        cin >> u >> v;
        Graph[u].push_back(v);
    }
    queue<int> Que;
    for(int i = 1; i <= n; ++i) {
        memset(visited, 0, sizeof(visited));
        Que.push(i);
        visited[i] = 1;
        while(!Que.empty()) {
            int p = Que.front();
            Que.pop();
            arrive[i]--;
            arrive[p]++;
            for(auto k : Graph[p]) 
                if(!visited[k]) {
                    Que.push(k);
                    visited[k] = 1;
                }
        }
    }
    for(int i = 1; i <= n; ++i)
        res += arrive[i] > 0? 1 : 0;
    cout << res << endl;
    return 0;
}

标签

查找

MT19 K 的倍数

链接

K 的倍数_牛客题霸_牛客网 (nowcoder.com)

描述

序列中任意个连续的元素组成的子序列称为该序列的子串。 现在给你一个序列 $P$ 和一个整数 $K$ ,询问元素和是 $K$ 的倍数的子串的最大长度。 比如序列 $[1,2,3,4,5]$ ,给定的整数 $K$ 为 5 ,其中满足条件的子串为 ${5} 、{2,3} 、{1,2,3,4} 、{1,2,3,4,5}$ , 那么答案就为 5 ,因为最长的子串为 ${1,2,3,4,5}$ ;如果满足条件的子串不存在,就输出 0 。

数据范围: $1 \leq n \leq 10^5 , 0 \leq p_i \leq 10^5 , 1 \leq K \leq 10^5$

输入描述: 第一行包含一个整数 $\mathrm{N}, 1 \leq N \leq 10^5$ 。 第二行包含 $\mathrm{N}$ 个整数 $p i , p i$ 表示序列P第 $\mathrm{i}$ 个元素的值。 $0 \leq p i \leq 10^5$ 。第三行包含一个整数 $\mathrm{K}, 1 \leq K \leq 10^5$ 。

输出描述: 输出一个整数ANS,表示答案。

示例

示例1

输入:

5
1 2 3 4 5
5

输出:

5

示例2

输入:

6
3 1 2 7 7 7
4

输出:

5

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

#include <iostream>

using namespace std;

int main()
{
    long long n;
    scanf("%d", &n);
    long long p[n+1];
    p[0] = 0;
        for(int i=1 ; i<=n ; i++)
        {
            scanf("%lld", &p[i]);
            p[i] += p[i-1];
        }
    int k;
    scanf("%d", &k);
    for(int len=n ; len>0 ; len--)
    {
        for(int i=0 ; i<=n-len ; i++)
        {
            int j = i + len;
            if((p[j]-p[i]) % k == 0)
            {
                cout << len << endl;
                return 0;
            }
        }
    }
    cout << 0 << endl;
}

标签

穷举

MT20 抽牌

链接

抽牌_牛客题霸_牛客网 (nowcoder.com)

描述

桌上放了一堆牌,牌从上到下由 1 到 $\mathrm{n}$ 编号,每张牌上写有一个数字,第 $\mathrm{i}$ 张牌上的数字为 $\mathrm{a}_{\mathrm{i}}$ ,小明和小方在玩轮流取牌的游戏,每次每个人只能取一张牌,小明先取牌。 取牌规则如下,当一个人取牌时,他只能取当前牌堆中的最上面的一张或者最下面一张。小明和小方都采用随机取牌的策略,小明每次以概率 $\mathrm{p}$ 取最上面一张牌,以概率 1-p 取最下面一张牌;小方每次以概率 $q$ 取最上面一张牌,以概率 1-q 取最下面一张牌。 最后两人的得分为他们各自取到牌上的数字之和。问小明得分的数学期望。

数据范围: $1 \leq n \leq 1000 , 0 \leq P , Q \leq 100 , 1 \leq a_i \leq 13$ 。

输入描述: 第一行输入三个整数 $n , P , Q$ 。小明取最上面一张牌的概率 $p=P / 100$ ,小方取最上面一张牌的概率 $q=Q / 100$ 。接下来一行 $n$ 个数,每张牌上的数字。

输出描述: 输出答䅁,四舍五入保留三位小数。

示例

示例1

输入:

2 10 90
1 2

输出:

1.900

示例2

输入:

5 10 20
1 3 4 5 13

输出:

18.038

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

#include <stdio.h>
#include <malloc.h>


double expectation(double p,double q,int *a,int n)
{
    int i,k,l;
    double *b,*c,*d;
    b=(double *)malloc(sizeof(double)*n);
    c=(double *)malloc(sizeof(double)*n);
    if (n%2==0)
    {
        for (i=0;i<n-1;i++)
            b[i]=p*a[i]+(1-p)*a[i+1];
        k=1;
        l=n;
    }
    else
    {
        for (i=0;i<n;i++)
            b[i]=a[i];
        k=0;
        l=n;
    }
    for (;k<l-1;)
    {
        k=k+2;
        for (i=0;i<l-k;i++)
            c[i]=p*a[i]+p*q*b[i+2]+(p*(1-q)+(1-p)*q)*b[i+1]+(1-p)*a[i+k]+(1-p)*(1-q)*b[i];
        d=c;
        c=b;
        b=d;
    }
    return b[0];
}

int main()
{
    int n,P,Q;
    double p,q;
    scanf("%d %d %d",&n,&P,&Q);
    int *a;
    a=(int *)malloc(sizeof(int)*n);
    int i;
    for (i=0;i<n;i++)
        scanf("%d",&a[i]);
    p=((double)P)/100;
    q=((double)Q)/100;
    double E;
    E=expectation(p,q,a,n);
    printf("%.3f",E);
    return 0;
}

标签

模拟

MT21 公约数

链接

公约数_牛客题霸_牛客网 (nowcoder.com)

描述

桌面上有 $n$ 张牌,每张牌上写了一个数字,第 $\mathrm{i}$ 张牌的数字为 $\mathrm{a}{\mathrm{i}}$ 。现在从中选出 $\mathrm{K}$ 张牌,把选出牌上的数字全部乘起来,得到一个数 $\mathrm{X}{\text {。 }}$ 问有多少种不同的选择方案,使得 $X$ 和 $A$ 的最大公约数大于等于 $B$ 。

数据范围: $2 \leq n \leq 50 , 2 \leq k \leq n, 1 \leq B \leq A \leq 10^5 , 1 \leq a_i \leq 10^5$

输入描述: 第一行第 $n , k , a , b$ 。接下来一行 $n$ 个数,每张牌上的数字

输出描述: 输出方案数

示例

示例1

输入:

5 2 12 6
4 4 1 2 3

输出:

3

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

#include<bits/stdc++.h>
using namespace std;
const int maxn=120;
long long int arr[maxn];
long long int dp[100010][52];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    long long int n,k,a,b;
    cin>>n>>k>>a>>b;
    for(int i=0;i<n;++i)
        cin>>arr[i];
    vector<int>vec;
    vec.push_back(1);
    vec.push_back(a);
    for(int i=2;i*i<=a;++i)
    {
        if(a%i==0)
        {
            vec.push_back(i);
            if(a/i!=i)
                vec.push_back(a/i);
        }
    }
    sort(vec.begin(),vec.end());
    for(int i=0;i<n;++i)
    {
        for(int j=k;j>0;--j)
        {
            if(j==1)
            {
                dp[__gcd(arr[i],a)][j]+=1;
                break;
            }
            for(int l=0;l<vec.size();++l)
            {
                dp[__gcd(arr[i]*vec[l],a)][j]+=dp[vec[l]][j-1];
            }
        }
    }
    long long int ans=0;
    for(int i=b;i<=a;++i)
    {
        ans+=dp[i][k];
    }
    cout<<ans<<"\n";
    return 0;
}

标签

基础数学

MT22 双袋购物

链接

双袋购物_牛客题霸_牛客网 (nowcoder.com)

描述

一条马路上有 $n$ 个点,从左到右从 1 到 $n$ 编号。小明一开始在马路的最左边,一直往右走,一直走到马路的最右边,一直往右走,一直走到马路的最右边,中途不允许回 头,只能往右走。

每个点上都有一个物品,第 $\mathrm{i}$ 个点的物品体积为 $\mathrm{v}{\mathrm{i}}$ ,价值为 $\mathrm{w}{\mathrm{i}}$ , (注意:先输入体积再输入价值) 小明有两个袋子,一号袋子和二号袋子,一号袋子体积为 $\mathrm{A}$ ,二号袋子体积为 $B$ 。

最开始小明使用一号袋子,经过一个点的时候,他可以选择把点上的物品放入袋子中,但是袋中物品的总体积不能超过袋子的体积,也可以选择不拿这个物品。 在整个过程中的任意一个时刻,小明可以选择把一号袋子收起来,接下来使用二号袋子,一旦小明收起了一号袋子,之后他再也不能使用一号袋子,接下来的物品只能决策 是否放入二号袋子中,且袋中的物品的总体积不能超过袋子容量。特别的,小明可以在最开始(遇到 1 号点之前) 就换袋子,这样他全程都使用二号袋子;他也可以一直 使用一号袋子,到最后也不收。

小明最后获得的价值为两袋子中物品价值和,问在最优策略下的最大价值。

数据范围: $1 \leq n, A, B, v_i, w_i \leq 1000$

输入描述: 输入第一行三个数 $n, A$, B。接下里有 $n$ 行,每行两个数 $v_{-} i, w_{-} i$ 衣次表示每个物品的体积和价值。

输出描述: 输出一个数,最大价值

示例

示例1

输入:

5 10 50
3 3
7 4
4 7
49 50
2 2

输出:

60

说明:

用一号袋子装1号和3号物品,之后收起一号袋子,用二号袋子装4号物品。 

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
    int n,A,B,idx=0;
    cin>>n>>A>>B;
    vector<int> value(n);
    vector<int> weight(n);
    while(n--){
        cin>>weight[idx]>>value[idx];
        idx++;
    }
    n=(int)value.size();
    vector<int> All_A(n,0);
    vector<int> All_B(n,0);
    vector<int> dpA(A+1,0);
    vector<int> dpB(B+1,0);
    for(int i=0;i<n;++i){
        for(int j=A;j>=weight[i];--j)
            dpA[j]=max(dpA[j],dpA[j-weight[i]]+value[i]);
        All_A[i]=dpA[A];
    }
    for(int i=n-1;i>=0;--i){
        for(int j=B;j>=weight[i];--j)
            dpB[j]=max(dpB[j],dpB[j-weight[i]]+value[i]);
        All_B[i]=dpB[B];
    }
    int combination=0;
    for(int i=0;i<n-1;++i)
        combination=max(combination,All_A[i]+All_B[i+1]);
    cout<<combination;
    return 0;
}

标签

动态规划

MT23 友好城市

链接

友好城市_牛客题霸_牛客网 (nowcoder.com)

描述

某国家一共有 $n$ 座城市,有的城市与城市与城市之间有路相连,所有的路都是无向的, $n$ 个城市可以通过道路相互达到,其中 $2 k$ 座城市是重要城市,国王希望把这 $2 k$ 座城市两两 配对,形成 $k$ 对友好城市。 友好城市之间常常需要进行交流,因此国王希望友好城市之间的距离不要太长,于是他定义两个城市 $u , v$ 配对的代价为 $u , v$ 之间最短路的长度,2 $k$ 座城市配对的总代价为 $k$ 对城 市配对的代价和。 国王想知道配对的最小代价。

数据范围: $2 \leq n \leq 100 , 1 \leq A[i][j] \leq 1000$ 或 $A[i][j]=-1 , 1 \leq K \leq 8 , 2 \times k \leq n$

输入描述: 第一行输入一个数 $n$ ,表示城市个数。接下来输入一个 $n^* n$ 的邻接矩阵 $A , A[i][]$ 表示城市 $i$ 和 城市 $j$ 之间边的长度,如果 $A[i][j]=-1$ ,表示 $i$ 和 $j$ 之间没有直接相连的边,输入保 证 $A[i][j]=A[j][i] , A[i][i]=-1$ ,且 $n$ 个城市相互连通。最后输入一个数 $k$ ,接下来一行 $2 k$ 个数,这 $2 k$ 个重要城市的编号

输出描述: 输出一个数,最小匹配代价

示例

示例1

输入:

4
-1 2 -1 10
2 -1 3 -1
-1 3 -1 1
10 -1 1 -1
2
1 2 3 4

输出:

3

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

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

int n, k, a[101][101], b[101], Min=INT_MAX;

void DFS(int cnt, int s){
    if(cnt==2*k){
        Min = min(Min, s);
        return;
    }
    for(int i=cnt+1;i<2*k;i++){
        swap(b[i], b[cnt+1]);
        DFS(cnt+2, s+a[b[cnt]][b[cnt+1]]);
        swap(b[i], b[cnt+1]);
    }
}

int main(){
    scanf("%d", &n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%d", &a[i][j]);
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(i!=j && a[i][k]!=-1 && a[k][j]!=-1){
                    if(a[i][j]==-1)
                        a[i][j] = a[i][k] + a[k][j];
                    else
                        a[i][j] = min(a[i][j], a[i][k]+a[k][j]);
                }
    scanf("%d", &k);
    for(int i=0;i<2*k;i++)
        scanf("%d", &b[i]);
    DFS(0, 0);
    printf("%d\n", Min);
    return 0;
}

标签

图 dfs

MT24 吃鱼

链接

吃鱼_牛客题霸_牛客网 (nowcoder.com)

描述

小田非常喜欢吃鱼,特别喜欢煎着吃。有一天她抓到了 $\mathrm{n}$ 条鱼,她有一个煎锅,每次可以同时煎 $\mathrm{m}$ 条鱼。这个煎锅可以花一分钟的时间煎熟鱼的一面,当一条鱼的两面都煎熟了它就 可以吃了。现在她想知道最少需要花多少时间能够把所有的鱼都煎熟。

数据范围: $1 \leq n, m \leq 500$

输入描述: 第一行包含两个整数 $n, m_{\text {。 }}$

输出描述: 输出对应的答宴。

示例

示例1

输入:

3 2

输出:

3

示例2

输入:

4 2

输出:

4

示例3

输入:

1 4

输出:

2

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

#include <iostream>
using namespace std;
#include <math.h>

int main()
{
    double n,m;
    cin>>n>>m;
    if (n<=m)
    {
        cout<<2<<endl;
    }
    else{
         cout<<ceil(2*n/m)<<endl;
    }

    return 0;
}

标签

思维

MT25 超链接

链接

超链接_牛客题霸_牛客网 (nowcoder.com)

描述

很多网页上会显示一些其他网页的超链接,如一些搜索网页会逐条列出搜索到的条目。 在一些网页中,被用户点击过的超链接会换一种颜色显示。假设某网页一开始有 $n$ 条超链接,从上到下由 1 到 $n$ 编号,每条超链接都显示成一个字符串,最开始所有的超链接用蓝色显示。 现在给出用户点击过哪些超链接,一条超链接只要被点击过了,就会由蓝色变成紫色,请输出最后仍为蓝色的超链接。

数据范围: $1 \leq n \leq 100 , 1 \leq m \leq 100$

输入描述: 第一行输入一个数 $n$ ,接下来 $n$ 行,每行一个字符串,表示每个超链接的名称,名称只由小写字母构成,长度不超过 20,且所有名称互不相同。接下来输入一个数 $\mathrm{m}$ ,表示用户点击 了 $m$ 个超链接,最后 $m$ 行表示用户点击过的超链接名称,这 $m$ 个超链接中可能有重复。

输出描述: 输出若干行,每行一个名称,所有仍为蓝色的超链接名称,名称的顺序按照字典序排序,如果全为紫色则不输出。

示例

示例1

输入:

5
sina
qq
taobao
jd
baidu
3
qq
baidu
baidu

输出:

jd
sina
taobao

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

#include<cstdio>
#include<set>
#include<string>
#include<vector>

using namespace std;

int main(){
    int n;
    scanf("%d",&n);
    set<string> links;
    for(int i=0;i<n;++i){
        char c[101];
        scanf("%s",c);
        string s=c;
        links.insert(s);
    }

    int m;
    scanf("%d",&m);
    for(int i=0;i<m;++i){
        char c[101];
        scanf("%s",c);
        string clicked=c;
        if(links.find(clicked)!=links.end()){
            links.erase(clicked);
        }
    }

    for(auto &s:links){
        printf("%s\n",s.c_str());
    }

    return 0;
}

标签

哈希

MT26 改考卷

链接

改考卷_牛客题霸_牛客网 (nowcoder.com)

描述

在上小学的时候,我们经常碰到这样的事:考完试后老师懒得改试卷,于是让我们同桌相互交换试卷后为对方批改。但是后来老师发现这样作容易出现作弊,于是他想了一个新办法。老师将同学分成了 $\mathrm{n}$ 个组,其中编号为 $i$ 的组中有 $s_i$ 个人。然后老师会按某种顺序依次访问 这些组。对于他访问的第一个组,他会将这组内的所有试卷都收走,放置在桌上对于他后续访问的每一个组,首先他会从桌上的试卷最上方拿出该组对应人数数量的试卷,随机分配给该组每个人一张试卷让他们进行批改,而后再将这组学生自己考的试卷收走放置在桌面试卷的最下方。当他访问完 所有的组后他会将桌面上剩余的所有试卷随机分配给他第一个访问的组的学生进行批改。但他发现这种方法有时候也会出现问题.有可能在中途访问到某个组的时候桌面上的试卷不够分配给这组学生每人一张; 也有可能最后会有学生分配到批改自己的试卷,而且这两种情况是否出现是与他访问每个组的顺序有关的。现在他想知道是否存在一种访问顺序能够使以上两种情况都不出现,顺利完成试卷批改呢?

数据范围: $2 \leq n \leq 30 , 1 \leq s_i \leq 10000$

输入描述: 第一行包含一个整数 $n$ ,表示学生组数。 第二行包含 $n$ 个整数, $s_1, s_2, \ldots, s_n$ ,分别表示每组学生的人数。

输出描述: 若存在一种访问顺序能使试卷顺利批改完成,输出 Yes,否则输出 No。

示例

示例1

输入:

2
10 20

输出:

No

说明:

如果以 10 20 的顺序访问,则在第二组的时候作业不够第二组分,如果以 20 10 的顺序访问,则分给 20 人组的作业中有 10 本是本组的 

示例2

输入:

4
2 3 3 1

输出:

Yes

说明:

我们可以选择先访问人数为 3 的组,再访问人数为 3 的组,再访问人数
为 1 的组,最后访问人数为 2 的组。 

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

bool helper(vector<int> &a){
    sort(a.begin(), a.end(), greater<int>());
    int sum = 0;
    for(int i=1; i<a.size(); i++){
        if(a[i]>a[0]) return false;
        sum += a[i];
    }
    if(sum<a[0]) return false;
    return true;
}

int main(){
    int n;
    cin>>n;
    vector<int> a(n);
    for(int i=0; i<n; i++)
        cin>>a[i];
    printf("%s", helper(a)? "Yes" : "No");
}

标签

模拟

MT27 交错序列

链接

交错序列_牛客题霸_牛客网 (nowcoder.com)

描述

我们定义一个由数字 0 和 1 组成的序列是交错序列,当且仅当在这个序列中 0 和 1 是轮流 出现的,比如,0,010,10101都是交错序列。 现在給出了一个由数字 0 和 1 组成的序列 $A$ ,它可能不是一个交错序列,但是你可以从这个序列中选择一些数字出来,按他们在序列 $A$ 中原有的相对顺序排列(即选取 $A$ 的一个子序列),使得你最后得到的是一个交错序列。问这样能得到的交错序列的最长长度是多少。

数据范围: $1 \leq n \leq 10^5$ ,序列中只包含 0 和 1 。

输入描述: 第一行包含一个整数 $n$ ,表示输入序列的长度。 第二行包含 $n$ 个 0 或 1 ,表示对应的序列。

输出描述: 输出能够得到的最长交错序列的长度。

示例

示例1

输入:

3
0 1 0

输出:

3

示例2

输入:

8
1 1 0 0 1 1 0 0

输出:

4

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

#include<iostream>
#include<stdio.h>

using namespace std;

int main()
{
    int n;
    char op;
    char temp;
    scanf(" %d",&n);
    int length = 0;
    scanf(" %c",&temp);
    ++length;
    for(int i = 0; i < n - 1; i ++)
    {
        scanf(" %c",&op);
        if(temp ^ op) // 不相等
        {
            if((length & 1))
            {
                ++length;
            }
        }
        else
        {
            if(!(length & 1))
            {
                ++length;
            }
        }
    }
    printf("%d",length);
    return 0;
}

标签

字符串

MT28 手机号

链接

手机号_牛客题霸_牛客网 (nowcoder.com)

描述

很多网站都要求用户输入手机号码,现在请写一个程序,判断用户输入的手机号码是否合法。本题中定义的合法手机号和现实中的手机号有出入,解题时以题面定义为准。

一个合法的手机号码满足以下条件:

(1)手机号码由 11 位数字构成。

(2)手机号码的前三位为网络识别号,对应不同的手机运行商,在本题中只有以下几种(其余情况在本题中一律认为手机号不合法)

​ 中国电信:133,153,180,181,189

​ 中国联通:130,131,155,185,186

​ 中国移动:135,136,150,182,188

(3)剩下 8 位数字任意

现在输入手机号码,请判断是否合法

输入描述:

第一行一个数 T ,接下里 T 行每行一个手机号,输入的手机号只由数字构成。

输出描述:

输出 T 行,对每个手机号,如果满足题面定义, 电信号码输出 China Telecom 联通号码输出 China Unicom 移动号码输出 China Mobile Communications 如果不符合题面定义则输出 -1

示例

示例1

输入:

5
13312345678
18687654324
18277748494
15898494958
45364

输出:

China Telecom
China Unicom
China Mobile Communications
-1
-1

接口

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

题解

#include<cstdio>
#include<vector>
#include<unordered_map>
#include<string>

using namespace std;

int main(){

    unordered_map<string,string> mp{
        {"133","China Telecom"},
        {"153","China Telecom"},
        {"180","China Telecom"},
        {"181","China Telecom"},
        {"189","China Telecom"},
        {"130","China Unicom"},
        {"131","China Unicom"},
        {"155","China Unicom"},
        {"185","China Unicom"},
        {"186","China Unicom"},
        {"135","China Mobile Communications"},
        {"136","China Mobile Communications"},
        {"150","China Mobile Communications"},
        {"182","China Mobile Communications"},
        {"188","China Mobile Communications"},
    };

    int t;
    scanf("%d",&t);
    char c[21];
    vector<string> nb(t);
    for(int i=0;i<t;++i){
        scanf("%s",c);
        nb[i]=c;
    }

    for(int i=0;i<t;++i){
        if(nb[i].size()!=11){
            printf("-1\n");
        }
        else{
            if(mp.find(nb[i].substr(0,3))==mp.end()){
                printf("-1\n");
            }
            else{
                printf("%s\n",mp[nb[i].substr(0,3)].c_str());
            }
        }
    }
    return 0;
}

标签

字符串

[编程题]最优二叉树II

https://www.nowcoder.com/question/next?pid=28665343&qid=1371128&tid=62755916

小团有一个由 $N$ 个节点组成的二叉树,每个节点有一个权值。定义二叉树每条边的开销为其两端节点权值的乘积,二叉树的总开销即每条边的开销之和。小 团按照二叉树的中序遍历依次记录下每个节点的权值,即他记录下了 $\mathrm{N}$ 个数,第 $\mathrm{i}$ 个数表示位于中序遍历第 $\mathrm{i}$ 个位置的节点的权值。之后由于某种原因,小团遗 忘了二叉树的具体结构。在所有可能的二叉树中,总开销最小的二叉树被称为最优二叉树。现在,小团请小美求出最优二叉树的总开销。

小团有一个由 N 个节点组成的二叉树,每个节点有一个权值。定义二叉树每条边的开销为其两端节点权值的乘积,二叉树的总开销即每条边的开销之和。小 团按照二叉树的中序遍历依次记录下每个节点的权值,即他记录下了 N 个数,第i 个数表示位于中序遍历第 i 个位置的节点的权值。之后由于某种原因,小团遗 忘了二叉树的具体结构。在所有可能的二叉树中,总开销最小的二叉树被称为最优二叉树。现在,小团请小美求出最优二叉树的总开销。

由N个节点组成的二叉树 每个节点有一个权值 定义二叉树每条边的开销为其两端节点权值的乘积 二叉树的总开销即每条边的开销之和

链接

描述

示例

接口

题解

标签

[编程题]糕点

https://www.nowcoder.com/test/question/10661f4d02564ba686bcba4645e0a029?pid=28665338&tid=62757774 小团的蛋糕铺长期霸占着美团APP中“蛋糕奶杀”栏目的首位,因此总会吸引各路食客前来探店。 小团一天最多可以烤 $\mathrm{n}$ 个蛋糕,每个蛋糕有一个正整数的重量。 早上,糕点铺已经做好了 $\mathrm{m}$ 个蛋糕。 现在,有一个顾客要来买两个蛋糕,他希望买这一天糕点铺烤好的最重的和最轻的蛋糕,并且希望这两个蛋糕的重量怡好为 $a$ 和 $b$ 。剩余的 $n-m$ 个蛋糕可以现 烤,请问小团能否满足他的要求? 数据范围: $1 \leq m \leq n \leq 1000,1 \leq a, b \leq 1000$ 进阶:时间敗杂度 $O(m)$,空间复杂度 $O(m)$ 输入描述: 输入包含多组数据,每组数据两行。 每组数据的第一行包含 4 个整数, $n, m, a, b$ ,空格隔开。这里不保证a和 $b$ 的大小关系。 接下来一行 $\mathrm{m}$ 个数,空格隔开,代表烤好的蛋糕重量 输出描述: 对于每一组数据,如果可以办到顾客的要求,输出YES,否则输出NO

现在,有一个顾客要来买两个蛋糕,他希望买这一天糕点铺烤好的最重的和最轻的蛋糕,并且希望这两个蛋糕的重量怡好为 a 和 b 。剩余的 n-m 个蛋糕可以现 烤,请问小团能否满足他的要求

【编程笔试】美团2021校招笔试-通用编程题第9场(附思路及C++代码)

https://blog.csdn.net/qq_41084756/article/details/120083756 CSDN首页 博客 下载 学习 社区 GitCode 云服务 猿如意 编程题 搜索

会员中心 足迹 动态 消息 创作中心 发布 【编程笔试】美团2021校招笔试-通用编程题第9场(附思路及C++代码)

STARBLOCKSHADOW

于 2021-09-03 15:57:22 发布

636 收藏 1 分类专栏: 美团笔试 笔记 文章标签: 笔试 编程题 美团 版权

美团笔试 同时被 2 个专栏收录 10 篇文章2 订阅 订阅专栏

笔记 40 篇文章3 订阅 订阅专栏 导览 练习地址 糕点 晋级人数 回转寿司 神秘的苹果树 总结 练习地址 点此前往练习

糕点 小团的蛋糕铺长期霸占着美团APP中“蛋糕奶茶”栏目的首位,因此总会吸引各路食客前来探店。

小团一天最多可以烤n个蛋糕,每个蛋糕有一个正整数的重量。

早上,糕点铺已经做好了m个蛋糕。

现在,有一个顾客要来买两个蛋糕,他希望买这一天糕点铺烤好的最重的和最轻的蛋糕,并且希望这两个蛋糕的重量恰好为a和b。剩余的n-m个蛋糕可以现烤,请问小团能否满足他的要求?

输入描述:

输入包含多组数据,每组数据两行。每组数据的第一行包含4个整数,n,m,a,b,空格隔开。这里不保证a和b的大小关系。接下来一行m个数,空格隔开,代表烤好的蛋糕重量

输出描述:

对于每一组数据,如果可以办到顾客的要求,输出YES,否则输出NO

输入例子1:

4 2 2 4

3 3

4 2 2 4

1 1

4 2 2 4

5 5

4 2 4 2

2 4

2 2 2 4

3 3

3 2 2 4

3 3

3 2 2 4

3 3

输出例子1:

YES NO NO YES NO NO NO

思路:

由于输入的a和b不保证大小,因此需要处理一下,当a>b时,交换a和b,保证a小b大。

接着在输入已烤好蛋糕时记录最大值和最小值。

而后只需要考虑没烤好蛋糕的情况,共有三种情况:

(1)今天的面包都烤好了,此时只要a和最小值相等以及b和最大值相等即可;

(2)今天的面包还剩一个没烤,此时只要a或b中的一个重量满足最小值或最大值即可,剩下还没烤的一个可以满足要求;

(3)今天的面包多于两个没烤,此时只要a比最小值大且b比最大值小即可,剩下还没烤的面包可以满足要求。

代码:

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

int main() { int n,m,a,b; while(cin>>n>>m>>a>>b) { vector w(m); int rest=n-m; bool flag=0; if(a>b) swap(a,b); int maxv,minv; for(int i=0;i<m;i++) { cin>>w[i]; if(i==0) maxv=w[i],minv=w[i]; maxv=max(maxv,w[i]); minv=min(minv,w[i]); } if(rest==0&&a==minv&&b==maxv) flag=1; if(rest==1&&(a==minv||b==maxv)) flag=1; if(rest>=2&&minv>=a&&maxv<=b) flag=1; if(flag==1) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 晋级人数 小团是某综艺节目的策划,他为某个游戏环节设计了一种晋级规则,已知在这个游戏环节中每个人最后都会得到一个分数score_i,显而易见的是,游戏很有可能出现同分的情况,小团计划该环节晋级人数为x人,则将所有人的分数从高到低排序,所有分数大于等于第x个人的分数且得分不为0的人都可以晋级。

请你求出本环节的实际晋级人数。显然这个数字可能是0,如果所有人的得分都是0,则没有人满足晋级条件。

输入描述:

输入第一行包含两个正整数n和x,分别表示参加本环节的人数,和小团指定的x。输入第二行包含n个整数,每个整数表示一位选手的得分。

输出描述:

输出仅包含一个整数,表示实际晋级人数。

输入例子1:

5 4

0 0 2 3 4

输出例子1:

3

思路:

对参加人数的分数进行降序排序,当得分比第x个人的得分高且得分不为0时,可以晋级。

代码:

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

int main() { int n,x; cin>>n>>x; vector s(n); int cnt=0; for(int i=0;i<n;i++) { cin>>s[i]; } sort(s.begin(),s.end(),greater ()); for(int i=0;i<n;i++) { if(s[i]>=s[x-1]&&s[i]!=0) cnt++; } cout<<cnt; return 0;
}

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 回转寿司 小美请小团吃回转寿司。转盘上有N盘寿司围成一圈,第1盘与第2盘相邻,第2盘与第3盘相邻,…,第N-1盘与第N盘相邻,第N盘与第1盘相邻。小团认为第i盘寿司的美味值为A[i](可能是负值,如果小团讨厌这盘寿司)。现在,小团要在转盘上选出连续的若干盘寿司,使得这些寿司的美味值之和最大(允许不选任何寿司,此时美味值总和为0)。

输入描述:

第一行输入一个整数T(1<=T<=10),表示数据组数。每组数据占两行,第一行输入一个整数N(1<=N<=105); 第二行输入N个由空格隔开的整数,表示A[1]到A[N](-104<= A[i] <=104)。

输出描述:

每组数据输出占一行,输出一个整数,表示连续若干盘寿司的美味值之和的最大值。

输入例子1:

1

4

3 -2 4 -1

输出例子1:

6

例子说明1:

美味值之和最大连续若干盘寿司为第3盘、第4盘和第1盘。

思路:

成环的最大连续子数组和问题。

(1)不考虑环形,求得连续子数组的最大和及最小和;

(2)只考虑环形求得最大和及最小和。

如果不考虑环形求得的连续子数组的和达到了最小,那么总和减去这个最小值就等于环形情况的最大值了。

题中所求的最大美味值就是(1)和(2)中大的那一个。

理解第二种情况:首尾相连之后如果下一个A[i]增加贡献,可能会出现首尾相连之后连续和更大,对于这种情况直接按照原来方法求一遍连续子数组和最小,然后用所有数的和(sum)减去这个连续子数组的最小值和原来求连续子数组的全局最大值取一个max即可。原因在于sum求的是所有的数的和,这中间不乏计算了连续子数组和为负数的情况,因此将这个最小连续子数组和求出来,再用sum来减掉这个最小连续子数组和就成了首尾相连最大的情况。

代码:

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

int main() { int t; cin>>t; while(t--) { int n; cin>>n; vector a(n); int sum=0; for(int i=0;i<n;i++) { cin>>a[i]; sum+=a[i]; } int maxs=a[0],curmax=a[0]; int mins=a[0],curmin=a[0]; for(int i=1;i<n;i++) { curmax=max(a[i],a[i]+curmax); maxs=max(maxs,curmax); curmin=min(a[i],a[i]+curmin); mins=min(mins,curmin);
} cout<<max(sum-mins,maxs)<<endl; } return 0; }

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 神秘的苹果树 小团找到一颗有n个节点的苹果树,以1号节点为根,且每个节点都有一个苹果,苹果都有一个颜色,但是这棵树被施加了咒术,这使得小团只能从某一个节点的子树中选取某一种颜色的拿。小团想要拿到数量最多的那种颜色的所有苹果,请帮帮她。每次她会指定一个节点t,如果小团只能从节点t的子树中选取某一种颜色的苹果,选取什么颜色能拿到最多的苹果?如果有多种颜色都可以拿同样多的苹果,输出颜色编号最小的那个对应的编号。

节点x的子树定义为所有将x当作祖先的节点,x也视为x的子树的一部分。

输入描述:

第一行一个正整数n表示这颗树上节点的个数。

接下来n-1行,每行两个正整数x­­i,yi,表示树上第i条边连接的两个节点。

接下来一行n个正整数c­i,分别表示从1~n号节点上的苹果的颜色。

接下来一行一个正整数q,表示接下来有q次独立的询问。

接下来q行,每行一个正整数t表示询问:如果小团只能从节点t的子树中选取某一种颜色的苹果,选取什么颜色能拿到最多的苹果?如果有多种颜色都可以拿同样多的苹果,输出颜色编号最小的那个对应的编号。

对于100%的数据n≤5000, 1≤xi,yi,t≤n, ci≤1000000000,q≤1000

输出描述:

输出q行,每行一个整数,表示答案。

输入例子1:

7

1 2

1 3

2 4

2 5

3 6

3 7

1 1 2 1 2 2 3

7

1

2

3

4

5

6

7

输出例子1:

1 1 2 1 2 2 3

思路:

参考评论区中FengxiangHuang的思路:

因为颜色会重复,因此用multiset来存储每个节点的颜色集合,该集合可以通过递归得到,节点x的颜色集合为节点x所有子节点颜色集合相加再加上节点x的颜色。

代码:

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

typedef long long ll;

vector e[5100]; int c[5100], res[5100]; set st; multiset mt[5100];

void dfs(int root, int fa) { for (auto i:e[root]) { if (i == fa)continue; dfs(i, root), mt[root].insert(mt[i].begin(), mt[i].end()); } mt[root].insert(c[root]); int mx = 0, cat; for (auto i:st) { int num = mt[root].count(i); if (num > mx) mx = num, cat = i; } res[root] = cat; }

int main() { int n, x, y, q, m; cin >> n; for (int i = 1; i <= n - 1; ++i) { cin >> x >> y; e[x].push_back(y), e[y].push_back(x); } for (int i = 1; i <= n; ++i) { cin >> c[i]; st.insert(c[i]); } dfs(1, -1); cin >> q; for (int i = 0; i < q; ++i) { int t; cin >> t; printf("%d\n", res[t]); } return 0; }

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 总结 第四题:

C++ STL中multiset:关联容器,已排序好的集合,允许有相同元素。 头文件:#include 创建multiset对象:multiset mt; 插入元素: mt.insert(begin,end);将区间[begin,end)所有的元素插入mt中,无返回值。 mt.insert(x);插入一个x副本,返回新元素位置,无论插入成功与否。 mt.insert(pos,x);插入一个x元素副本,返回新元素位置,pos为搜索起点,提升插入速度。 删除元素: mt.erase(begin,end);移除区间[begin,end)的所有元素,无返回值。 mt.erase(x);删除与x相等的所有元素,返回被移除的元素个数。 mt.erase(pos);移除迭代器pos所指位置元素,无返回值。 清空集合:mt.clear();移除所有元素,将容器清空。 返回元素值为x的个数:mt.count(x); 查找元素值为x的第一个元素:mt.find(x);如果没有返回end()。 返回元素数量:mt.size();

STARBLOCKSHADOW 关注

0

1 打赏

0

专栏目录 美团笔试-回转寿司 zhaoxiaoba的博客 938 小美请小团吃回转寿司。转盘上有N盘寿司围成一圈,第1盘与第2盘相邻,第2盘与第3盘相邻,…,第N-1盘与第N盘相邻,第N盘与第1盘相邻。小团认为第i盘寿司的美味值为A[i](可能是负值,如果小团讨厌这盘寿司)。现在,小团要在转盘上选出连续的若干盘寿司,使得这些寿司的美味值之和最大(允许不选任何寿司,此时美味值总和为0)。 输入: 第一行输入一个整数T(1<=T<=10),表示数据组数。 每组数据占两行,第一行输入一个整数N(1<=N<=10^5); 第二行输入N个由空格隔开的整数, 2021美团笔试题(第十套)个人解答 flyersboy的博客 2839 1、淘汰分数 //暴力解法 import java.util.Arrays; import java.util.Scanner; /* * 先排序,从最小值开始遍历,判断两者人数是否符合人数区间 * 注意:考虑存在多个分数线时,要输出最低的,所以要排序 * / public class EliminateScores { public static int findEliminateScores(int min, int max, int[] scores) { if (min 美团2021校招笔试-编程题(通用编程试题,第9场) m0_46663240的博客 741 第一题题目没看懂团的蛋糕铺长期霸占着美团APP中“蛋糕奶茶”栏目的首位,因此总会吸引各路食客前来探店。小团一天最多可以烤n个蛋糕,每个蛋糕有一个正整数的重量。早上,糕点铺已经做好了m个蛋糕。现在,有一个顾客要来买两个蛋糕,他希望买这一天糕点铺烤好的最重的和最轻的蛋糕,并且希望这两个蛋糕的重量恰好为a和b。剩余的n-m个蛋糕可以现烤,请问小团能否满足他的要求按答案意思是顾客的要求是已经烤好的m个蛋糕的重量应该介于a\b之间。 关键理解n是什么作用,n-m是现烤的,现烤的是完全可以满足要求的,如果烤好的已经超过 美团笔试题——蛋糕奶茶(python) weixin_43763858的博客 647 美团笔试题——蛋糕奶茶 小团的蛋糕铺长期霸占着美团APP中“蛋糕奶茶”栏目的首位,因此总会吸引各路食客前来探店。 小团一天最多可以烤n个蛋糕,每个蛋糕有一个正整数的重量。 早上,糕点铺已经做好了m个蛋糕。 现在,有一个顾客要来买两个蛋糕,他希望买这一天糕点铺烤好的最重的和最轻的蛋糕,并且希望这两个蛋糕的重量恰好为a和b。剩余的n-m个蛋糕可以现烤,请问小团能否满足他的要求? 输入描述: 输入包含多组数据,每组数据两行。 每组数据的第一行包含4个整数,n,m,a,b,空格隔开。这里不保证a和b的大小关系。 美团笔试题 小默学习笔记 1640 三、回转寿司 题目描述: 小美请小团吃回转寿司。转盘上有N盘寿司围成一圈,第1盘与第2盘相邻,第2盘与第3盘相邻,…,第N-1盘与第N盘相邻,第N盘与第1盘相邻。小团认为第i盘寿司的美味值为A[i](可能是负值,如果小团讨厌这盘寿司)。现在,小团要在转盘上选出连续的若干盘寿司,使得这些寿司的美味值之和最大(允许不选任何寿司,此时美味值总和为0)。 输入描述 第一行输入一个整数T(1<=T<=10),表示数据组数。 每组数据占两行,第一行输入一个整数N(1<=N<=10^5); 2020美团前端笔试题 qq_41800649的博客 4625 美团: 题目1:蛋糕奶茶(数组) 题目描述: 小团的蛋糕铺长期霸占着美团APP中“蛋糕奶茶”栏目的首位,因此总会吸引各路食客前来探店。 小团一天最多可以烤n个蛋糕,每个蛋糕有一个正整数的重量。 早上,糕点铺已经做好了m个蛋糕。 有一个顾客要来买两个蛋糕,他希望买这一天糕点铺中最重的和最轻的蛋糕,并且希望这两个蛋糕的重量恰好为a和b。剩余的n-m个蛋糕可以现烤,请问小团能否满足他的要求? 输入描述: 输入包含多组数据,每组数据两行。 每组数据的第一行包含4个整数,n,m,a,b,空格隔开。这里不保证a和b的 算法-DFS pourtheworld的博客 151 算法-DFSDFS暴力回溯1. 2021-4-7 两次回溯2. 2021-4-8 无向图转有向图 DFS 暴力回溯 1. 2021-4-7 两次回溯 题目: 现在有n个物品,每一个物品都有一个价值,现在想将这些物品分给两个人,要求这两个人每一个人分到的物品的价值总和相同(个数可以不同,总价值相同即可),剩下的物品就需要扔掉,现在想知道最少需要扔多少价值的物品才能满足要求分给两个人。 输入描述: 第一行输入一个整数 T,代表有 T 组测试数据。 对于每一组测试数据,一行输入一个整数 n ,代表物品的个数。 [SDOI2017]苹果树 题解 weixin_42465242的博客 106 首先,观察题意,可以发现在最长链下再接一个点,结果一定更优。 也就是说,可以免费选一条最长链,之后正常选。 我们枚举选的最长链,然后算出剩下部分的最优解。 有4部分: 1、链上每个点都选一个。 2、链上剩下的部分。 3、链的左面。 4、链的右面。 1可以直接计算。 那么,我们需要先进行树形背包,然后再通过某方式将其余3个合并。 我们知道,在此问题中,合并2个背包是O(k)的; 但... 最大美味度 盏息的博客 469 最大美味度 作者:糖橘蜜ya 声明:转载请注明出处,谢谢。 Description 有一个装糖果的盒子的容量为m(1&amp;amp;amp;amp;lt;=m&amp;amp;amp;amp;lt;=40000),有n(1&amp;amp;amp;amp;lt;=n&amp;amp;amp;amp;lt;=16)种糖果,每种糖果有体积v(1&amp;amp;amp;amp;lt;=v&amp;amp 『异或粽子 堆 可持久化trie』 weixin_30952103的博客 32 异或粽子 Description 小粽是一个喜欢吃粽子的好孩子。今天她在家里自己做起了粽子。 小粽面前有 n 种互不相同的粽子馅儿,小粽将它们摆放为了一排,并从左至右编号为 1 到 n。第 i 种馅儿具有一个非负整数的属性值 ai。每种馅儿的数量都足够多,即小粽不 会因为缺少原料而做不出想要的粽子。小粽准备用这些馅儿来做出 k 个粽子。 小粽的做法是:选两个整数数 l, r... iOS算法--美团 旋转寿司 张福润的博客 391 题目 小美请小团吃回转寿司。转盘上有N盘寿司围成一圈,第1盘与第2盘相邻,第2盘与第3盘相邻,…,第N-1盘与第N盘相邻,第N盘与第1盘相邻。小团认为第i盘寿司的美味值为A[i](可能是负值,如果小团讨厌这盘寿司)。现在,小团要在转盘上选出连续的若干盘寿司,使得这些寿司的美味值之和最大(允许不选任何寿司,此时美味值总和为0)。 输入描述: 第一行输入一个整数T(1<=T<=10),表示数据组数。 每组数据占两行,第一行输入一个整数N(1<=N<=10^5); 第二行输入N个由空 Last mile of the way(NOIP2017模拟题) Welcome to yjjr's blog! 838 小A从仓库里找出了一棵n个点的有根树,1号节点为这棵树的根,树上每个节点的权值为wi, 大小为ai。 现在他心中产生了Q个疑问,每个疑问形如在x的子树里,选出一些大小和不超过s的节点(不可以重复选一个节点),最大权值和可以为多少。 输入格式 一行一个整数n。 n−1行两个整数ui, vi表示一条边。 N每行两个整数wi, ai表示这个点的权值和大小。 一行一个整数Q。 每行两个整数 小Biu的树(树形dp) VUno)UKGzseI 505 小Biu的树(树形dp) 题目描述 小Biu有一颗有根树,树上有n个节点(编号1~n)。其中每个节点有一个苹果,每个苹果有一定的能量,现在小Biu和小Piu分别选出一棵子树,要求两棵子树不能相交而且所有苹果的能量和最大。 输入 第一行输入一个正整数 n(1... 3.26 美团笔试题C++ simple_lzx的博客 1099 * 3.26 美团笔试题C++ ** 1.小美因为各种原因无法按时返校。为了完成学业,小美只能在家里上网课。网课由n个课程视频组成,编号为1到n。每个视频都需要从头看到尾才算完成该部分的学习,且某些视频只能在看完指定的一些视频之后才能开始播放。因为小美的学习能力和她用来上网课的电脑性能都很强,所以小美可以同时观看任意多个课程视频。现在小美想知道,若她不眠不休地学习,每个课程视频最早能在她开始学习多长时间之后才能结束。 2.给你一个只包含小写字符的字符串s,你可以按任意顺序重排这个字符串中的字符,请问重排过 【2022-08-27】美团秋招笔试前四道编程题 最新发布 试问道几许 258 小美在摆弄她的字符串。最近小团送了小美一个特殊字符 ' * ',这个字符可以和其他所有字符匹配,除了这个字符外,其他字符只能自... 【编程笔试】美团2021校招笔试-通用编程题第1场(附思路及C++代码) Sig的博客 1604 导览练习地址小美的送花路线小美的评分计算器小美的外卖省钱计划小美的代金券要过期啦总结 练习地址 点此前往练习 小美的送花路线 小美是美团的一名鲜花快递员,鲜花是一种保质期非常短的商品,所以需要尽快送到客户手中,公司对于骑手的一个要求就是要规划送花的线路,使得骑手送完所有订单走的路程尽可能少。 (骑手开始派送时带走了所有需要派送的花,不必每单后返回花店,路程结算是从花店出发,到送完最后一名客户为止,不计算从最后一名客户家回到花店的时间) 公司对于骑手的绩效评价是取决于两个指标,一是从花店到所有客户地址的距离之 美团java笔试题_美团笔试题目(Java后端5题2小时) weixin_36327991的博客 2823 美团笔试题一共5题时间为2个小时美团的题难度适中(相对于阿里),有简单的题,也有难题,都需要考虑一些特殊情况第一题:题目:某学校的期末考试共有n个学生参加,考试科目共有m科。学校将会给一部分学生颁发单科成绩优秀奖,获奖学生需要满足的条件是某一科的成绩是所有学生中最高的或是最高的之一。请问学校应该给多少名学生颁发单科成绩优秀奖。输入:输入第一行包含两个正整数n和m,分别代表学生人数和考试科目数量。(... 【2022-08-20】美团秋招笔试五道编程题 试问道几许 1143 【2022-08-20】美团秋招笔试五道编程题 美味的序列(贪心+优先队列) upc122的博客 226 链接:美味的序列 来源:牛客网 题目描述 Cubercsl 喜欢吃序列,所以这一天不知道谁送了他一个序列,他非常快乐,想把他吃完。 序列的每一段自然也有好吃与不好吃的分别,他用数字标识了每个部分的美味度(可能是负的)。 现在,他可以从头或从尾部花费 1 秒吃掉这个序列的一个元素,并获得这个元素此时的美味度。但是,令他头疼的是,每经过 1秒,所有还没有被吃的部分的美味度会下降 1。 现在 Cuber... “相关推荐”对你有帮助么?

非常没帮助

没帮助

一般

有帮助

非常有帮助 ©️2022 CSDN 皮肤主题:精致技术 设计师:CSDN官方博客 返回首页 关于我们 招贤纳士 商务合作 寻求报道

400-660-0108

kefu@csdn.net

在线客服 工作时间 8:30-22:00 公安备案号11010502030143 京ICP备19004658号 京网文〔2020〕1039-165号 经营性网站备案信息 北京互联网违法和不良信息举报中心 家长监护 网络110报警服务 中国互联网举报中心 Chrome商店下载 账号管理规范 版权与免责声明 版权申诉 出版物许可证 营业执照 ©1999-2022北京创新乐知网络技术有限公司

STARBLOCKSHADOW 码龄5年 暂无认证 46 原创 6万+ 周排名 1万+ 总排名 11万+ 访问

等级 1302 积分 79 粉丝 96 获赞 72 评论 490 收藏 分享学徒 分享小兵 签到新秀 签到达人 签到王者 持之以恒 1024勋章 勤写标兵 新人勋章 阅读者勋章 私信 关注 搜博主文章

热门文章 【论文】论文中的参考文献:国标GB/T 7714-2015文献类型与格式 11871 CNN经典模型之LeNet-5模型 10789 python下运用keras中内置的ImageDataGenerator实现图像的简单增广 8162 MarkDown中写流程图的方法 7791 CenterNet配置及问题详解 7539 分类专栏

Unity 10篇

C# 3篇

笔试总结 1篇

毕业论文 2篇

美团笔试 10篇

数据结构与算法 1篇

游戏 2篇

读书笔记 2篇

医学影像 3篇

Linux 2篇

网络安全 2篇

笔记 40篇

目标检测 7篇

CNN 1篇

奇招妙计 6篇

最新评论 【持续更新中】Unity常见问题及其解决 programmer_ada: 开发游戏的人,是否自己会经常玩很多游戏呢?

【编程笔试】美团2021校招笔试-通用编程题第1场(附思路及C++代码) github_35727128: 第四题的思路不正确。 对于“1 1 1 2 3 4”这样的序列,优先合并后两个1收益更大;而对于“4 3 2 1 1 1”这样的序列,优先合并前两个1收益更大。

【编程笔试】美团2021校招笔试-通用编程题第3场(附思路及C++代码) FantasyQaQ: 为什么文中的<小美的区域会议>这题的代码不能AC?

Unity使用VS2019打开代码出现不兼容的解决方法 m0_58598212: 你好,没太看懂,请问怎么操作的?

Unity使用VS2019打开代码出现不兼容的解决方法 远去的时光31: 好了,谢谢博主

您愿意向朋友推荐“博客详情页”吗?

强烈不推荐

不推荐

一般般

推荐

强烈推荐 最新文章 【Unity】出现NullReferenceException:Object reference not set to an instance of an object.的原因总结 【Unity】打包WebGL项目遇到的问题及解决记录 【持续更新中】C#常见问题及其解决(VS2019) 2022年7篇2021年19篇2019年19篇2018年1篇

目录 导览 练习地址 糕点 晋级人数 回转寿司 神秘的苹果树 总结

举报

链接

描述

示例

接口

题解

标签

(入门题,熟悉考试环境)

输入处理(重要):HJ5.进制转换

https://www.nowcoder.com/practice/8f3df50d2b9043208c5eed283d1d4da6?tpId=37&tqId=21228&rp=1&ru=/exam/oj&qru=/exam/oj&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26pageSize%3D50%26search%3D%26tab%3D%25E5%2590%258D%25E4%25BC%2581%25E7%259C%259F%25E9%25A2%2598%26topicId%3D37&difficulty=undefined&judgeStatus=undefined&tags=&title= 描述 写出一个程序,接受一个十六进制的数,输出该数值的十进制表示。 数据范围: 保证结果在 $1 \leq n \leq 2^{31}-1$ 输入描述: 输入一个十只进制的数值字符串。 输出描述: 输出该数值的十进制字符串。不同组的测试用例用 $\backslash$ 隔开。

输入: 0xAA

输出: 170

#include<iostream>
#include<string>
#include<cmath>
using namespace std;
 int main()
 {
     string s;
     while(cin>>s)
     {
         int bit=0;
         int ans =0;
         for(int i=s.length()-1;i>1;i--)
         {
             if(s[i]>='0'&&s[i]<='9')
                 ans+=(s[i]-'0')*pow(16,bit++);
             else if(s[i]>='A'&&s[i]<='F')
                 ans+=(s[i]-'A'+10)*pow(16,bit++);
         }
         cout<<ans<<endl;
     }
     return 0;
 }

排列组合:(牛客搜索)NC61.两数之和

两数之和_牛客题霸_牛客网 (nowcoder.com)

https://zhuanlan.zhihu.com/p/464425153 给出一个整型数组 numbers 和一个目标值 target,请在数组中找出两个加起来等于目标 值的数的下标, 返回的下标按升序排列。 (注: 返回的数组下标从1开始算起,保证target一定可以由数组里面 2 个数字相加得到) 数据范围: $2 \leq \operatorname{len}($ numbers $) \leq 10^5 ,-10 \leq$ numbers $s_i \leq 10^9 , 0 \leq$ target $\leq 10^9$ 要求: 空间复杂度 $O(n)$ ,时间复杂度 $O(n \log n)$

class Solution {
public:
    vector<int> twoSum(vector<int> &numbers, int target) {
        map<int, int> mymap;
    vector<int> re;
    int i;
    for (i = 0; i < numbers.size(); ++i) {
        mymap[numbers[i]] = i+1;
    }


    for (i = 0; i < numbers.size(); ++i) {
        int a = numbers[i];
        int b = target - a;
        map<int, int>::iterator map_it = mymap.begin();
        map_it = mymap.find(b);
        if (map_it != mymap.end()) {
            int index1 = i+1;
            int index2 = map_it->second;
            if (index1 < index2) {
                re.push_back(index1);
                re.push_back(index2);
            } else if(index1 > index2) {
                re.push_back(index2);
                re.push_back(index2);
            } else {
                continue;
            }
            break;
        }
    }
    return re;
    }
};

快速排序:HJ3.明明的随机数 较难

https://www.nowcoder.com/practice/3245215fffb84b7b81285493eae92ff0?tpId=37&rp=1&ru=%2Fexam%2Foj&qru=%2Fexam%2Foj&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26pageSize%3D50%26search%3D%26tab%3D%25E5%2590%258D%25E4%25BC%2581%25E7%259C%259F%25E9%25A2%2598%26topicId%3D37&difficulty=&judgeStatus=&tags=&title=&gioEnter=menu

明明生成了 $N$ 个1到 500 之间的随机整数。请你删去其中重欹的数字,即相同的数字只保 留一个,把其余相同的数去掉,然㕆再把这些数火小到大排序,按照排好的顺序输出。 数据范围: $1 \leq n \leq 1000 ,$ 输入的数字大小满足 $1 \leq v a l \leq 500$ 输入描述: 第一行先输入随机整数的个数 $N$ 。接下来的 $N$ 行每行输入一个整数,代表明明生成的 随机数。具体格式可以人参考下面的"示例"。 输出描述: 输出客行,表示输入数据处理后的结果

明明生成了N个1到500之间的随机整数 请你删去其中重欹的数字 即相同的数字只保留一个 把其余相同的数去掉 然后再把这些数从小到大排序 按照排好的顺序输出

输入: 3 2 2 1 复制 输出: 1 2 复制 说明: 输入解释: 第一个数字是3,也即这个小样例的N=3,说明用计算机生成了3个1到500之间的随机整数,接下来每行一个随机数字,共3行,也即这3个随机数字为: 2 2 1 所以样例的输出为: 1 2

#include <iostream>
using namespace std;
int main() {
    int N, n;
    while (cin >> N) {
        int a[1001] = { 0 };
        while (N--) {
            cin >> n;
            a[n] = 1;
        }
        for (int i = 0; i < 1001; i++)
            if (a[i])
                cout << i << endl;
    }
    return 0;
}

哈希表:HJ10.字符个数统计

https://www.nowcoder.com/practice/eb94f6a5b2ba49c6ac72d40b5ce95f50?tpId=37&rp=1&ru=%2Fexam%2Foj&qru=%2Fexam%2Foj&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26pageSize%3D50%26search%3D%26tab%3D%25E5%2590%258D%25E4%25BC%2581%25E7%259C%259F%25E9%25A2%2598%26topicId%3D37&difficulty=&judgeStatus=&tags=&title=&gioEnter=menu 描述 编写一个函数,计算字符串中含有的不同字符的个数。字符在 ASCII 码范围内( 0 127 ,包括 0 和 127),换行表示结束符,不算在字符里。不在范围内的不作统计。多个相 同的字符只计算一次 例如,对于字符串 abaca 而言,有 a、b、c 三种不同的字符,因此输出 3 。 数据范围: $1 \leq n \leq 500$ 输入描述: 输入一行没有空格的字符串。 输出描述: 输出 输入字符串 中范围在 $(0 ~ 127$ ,包括0和127)字符的种数。

编写一个函数 计算字符串中含有的不同字符的个数 字符在ASCII码范围内0 127 包括0和127 换行表示结束符 不算在字符里 不在范围内的不作统计 多个相同的字符只计算一次

示例1 输入: abc 复制 输出: 3 复制 示例2 输入: aaa 复制 输出: 1

#include <iostream>
#include <unordered_map>
using namespace std;
int main(){
    string s;
    unordered_map<char,int> mp;
    while(cin>>s){
        int n=s.size();
        for(int i=0;i<n;i++){
            mp[s[i]]++;
        }
        cout<<mp.size()<<endl;

    }
}

递归:NC68.跳台阶

https://www.nowcoder.com/practice/8c82a5b80378478f9484d87d1c5f12a4 描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个 $n$ 级的台阶总共有 多少种跳法 (先后次序不同算不同的结果)。 数据范围: $1 \leq n \leq 40$ 要求: 时间复杂度: $O(n)$ ,空间复杂度: $O(1)$

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

(带*题目与第一第二道题目难度相近,以下题目基本上覆盖知识点)

class Solution {
public:
    int jumpFloor(int number) {
        if(number <= 2)
        {
            return number;
        }
        vector<int>res(number + 1, 0);
        res[1] = 1;
        res[2] = 2;
        for(int i = 3; i <= number; i++)
        {
            res[i] = res[i - 1] + res[i - 2];
        }
        return res[number];
    }
};

字符串操作:

HJ17.坐标移动

https://www.nowcoder.com/practice/119bcca3befb405fbe58abe9c532eb29?tpId=37&rp=1&ru=%2Fexam%2Foj&qru=%2Fexam%2Foj&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26pageSize%3D50%26search%3D%26tab%3D%25E5%2590%258D%25E4%25BC%2581%25E7%259C%259F%25E9%25A2%2598%26topicId%3D37&difficulty=&judgeStatus=&tags=&title=&gioEnter=menu 描述 开发一个坐标计算工具, $A$ 表示向左移动, $D$ 表示向右移动, $W$ 表示向上移动, $S$ 表示向 下移动。从 $(0,0)$ 点开始移动,从输入字符串里面读取一些坐标,并将最终输入结果输 出到输出文件里面。 输入: 合法坐标为 $A$ (或者 $D$ 或者 $W$ 或者 $S)+$ 数字 (两位以内) 坐标之间以;分隔。 非法坐标点需要进行丢弃。如AA10; A1A; $% $$$; YAD; 等。 下面是一个简单的例子如: A10;S20;W10;D30;X;A1A;B10A11;;A10; 处理过程: 起点 $(0,0)$ $+A 10=(-10,0)$ $+S 20=(-10,-20)$ $+\mathrm{W} 10=(-10,-10)$ $+\mathrm{D} 30=(20,-10)$ $+\mathrm{x}=$ 无效 $+A 1 A=$ 无效 $+\mathrm{B} 10 \mathrm{~A} 11=$ 无效 $+$ 一个空不影响 $+\mathrm{A} 10=(10,-10)$ 结果 $(10,-10)$ 数据范围: 每组输入的字符串长度满足 $1 \leq n \leq 10000$ , 坐标保证满足 $-2^{31} \leq$ $x, y \leq 2^{31}-1$ ,且数字部分仅含正数

输入描述: 一行字符串 输出描述: 最终坐标,以逗号分隔

示例1 输入: $\mathrm{A} 10 ; \mathrm{S} 20 ; \mathrm{W} 10 ; \mathrm{D} 30 ; \mathrm{X} ; \mathrm{A} 1 \mathrm{A} ; \mathrm{B} 10 \mathrm{A} 11 ; ; \mathrm{A} 10$; 输出: $10,-10$

示例2 输入: $\mathrm{ABC} ; \mathrm{AKL} ; \mathrm{DA1}$; 输出: 0,0

开发一个坐标计算工具 A表示向左移动 D表示向右移动 W表示向上移动 S表示向下移动 从(0,0)点开始移动 从输入字符串里面读取一些坐标 并将最终输入结果输出到输出文件里面

输入: A10;S20;W10;D30;X;A1A;B10A11;;A10;

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

int main()
{
    string str;

    while(cin >> str)
    {
        //初始化坐标
        int x = 0, y = 0;
        //存储单步操作
        vector<string> steps;

        //把字符串拆分
        int wordlen = 0;
        for(int i = 0; i < str.size(); ++i)
        {
            while(str[i] != ';')
                wordlen ++, i ++;
            steps.push_back(str.substr(i - wordlen, wordlen));
            wordlen = 0;
        }
        //分解成功
        //for(auto x : steps) cout << x << endl;

        //对单个steps执行坐标变换
        for(int i = 0; i < steps.size(); ++i)
        {
            int num = 0;
            //长度3  A10
            if(steps[i].length() == 3 && steps[i][1] <= '9' && steps[i][1] >= '0' &&  steps[i][2] <= '9' && steps[i][2] >= '0')
                num = (steps[i][1] - '0') * 10 + steps[i][2] - '0';
            //长度2  A5
            if(steps[i].length() == 2 && steps[i][1] <= '9' && steps[i][1] >= '0')
                num = steps[i][1] - '0';

            switch(steps[i][0])//ASDW
            {
                case 'A': x -= num; break;
                case 'D': x += num; break;
                case 'W': y += num; break;
                case 'S': y -= num; break;
                default: break;
            }
        }
        cout << x << ',' << y << endl;
    }

    return 0;
}

HJ20.密码验证合格程序

https://www.nowcoder.com/practice/184edec193864f0985ad2684fbc86841?tpId=37&rp=1&ru=%2Fexam%2Foj&qru=%2Fexam%2Foj&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26pageSize%3D50%26search%3D%26tab%3D%25E5%2590%258D%25E4%25BC%2581%25E7%259C%259F%25E9%25A2%2598%26topicId%3D37&difficulty=&judgeStatus=&tags=&title=&gioEnter=menu 描述 密码要求: 长度超过8位 包括大小写字母. 数字. 其它符号, 以上四种至少三种 不能有长度大于 2 的包含公共元素的子串重复 (注: 其他符昊不含空格或换行) 数据范围: 输入的字符串长度满足 $1 \leq n \leq 100$ 输入描述: 一组字符串。 输出描述: 如果符合要求输出: $OK$, 否则输出 $NG$

密码要求 长度超过8位 包括大小写字母 数字 其它符号 以上四种至少三种 不能有长度大于2的包含公共元素的子串重复 (注: 其他符昊不含空格或换行)

021Abc9000 021Abc9Abc1 021ABC9000 021$bc9000

#include <iostream>
#include <string>
using namespace std;
int func1(string &n) {
    int t[4] = {0};
    for (int i = 0; i < n.size(); i++) {
        if (n[i] <= '9' && n[i] >= '0')
            t[0] = 1;
        else if (n[i] <= 'z' && n[i] >= 'a')
            t[1] = 1;
        else if (n[i] <= 'Z' && n[i] >= 'A')
            t[2] = 1;
        else
            t[3] = 1;
    }
    return t[0] + t[1] + t[2] + t[3];
}

bool func2(string &n) {
    for (int i = 0; i + 3 < n.size(); i++) {
        string d = n.substr(i, 3);
        if (n.find(d, i + 3) != -1) return true;
    }
    return false;
}
int main() {
    string n;
    while (cin >> n) {
        if ((n.size() <= 8) || func1(n) < 3 || func2(n))
            cout << "NG" << endl;
        else
            cout << "OK" << endl;
    }
}

*HJ23.删除字符串中出现次数最少的字符

删除字符串中出现次数最少的字符_牛客题霸_牛客网 (nowcoder.com)

描述 实现删除字符串中出现次数最少的字符,若出现次数最少的字符有多个,则把出现次数最 少的字符都删除。输出删除这些单词后的字符串,字符串中其它字符保持原来的顺序。 数据范围: 输入的字符串长度满足 $1 \leq n \leq 20$ ,保证输入的字符串中仅出现小写字母 输入描述: 字符串只包含小写英文字母, 不考虑非法输入,输入的字符串长度小于等于20个字节。 输出描述: 删除字符串中出现次数最少的字符后的字符串。

示例1

输入:

aabcddd

输出:

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

int main()
{
    string str;

    while(cin>>str)
    {
        int min=20;
        vector<int> Hash(26,0);
        for(int i=0;i<str.size();i++)
        {
            Hash[str[i]-'a']++;
        }
        for(int i=0;i<26;i++)
        {
            if(min>Hash[i]&&Hash[i]>0)
                min=Hash[i];
        }
        for(int i=0;i<str.size();i++)
        {
            if(Hash[str[i]-'a']!=min)
                cout<<str[i];
        }
        cout<<endl;
    }
    return 0;
}

*HJ33.整数与IP地址间的转换

整数与IP地址间的转换_牛客题霸_牛客网 (nowcoder.com)

描述原理:

ip地址的每段可以看成是一个0-255的整数,把每段拆分成一个二进制形式组合起来,然后把这个二进制数转变成 一个长整数。 举例:一个ip地址为10.0.3.193 每段数字 相对应的二进制数 10 00001010 0 00000000 3 00000011 193 11000001

组合起来即为:00001010 00000000 00000011 11000001,转换为10进制数就是:167773121,即该IP地址转换后的数字就是它了。

数据范围:保证输入的是合法的 IP 序列输入描述: 输入 1 输入IP地址 2 输入10进制型的IP地址 输出描述: 输出 1 输出转换成10进制的IP地址 2 输出转换后的IP地址

示例1

输入:

10.0.3.193
167969729

复制

输出:

167773121
10.3.3.193
#include <iostream>
#include <string>
#include <vector>
#include <stack>
using namespace std;

void test33(){
    string ip;
    long num;
    while (std::cin >> ip >> num) {
        vector<int> vec;
        string tmp;
        for (long i = 0; i < ip.length(); i++) {
            if (ip[i] != '.') {
                tmp += ip[i];
            }else{
                vec.push_back(atoi(tmp.c_str()));
                tmp.clear();
            }
            if (i == (ip.length()-1)){
                vec.push_back(atoi(tmp.c_str()));
                tmp.clear();
            }
        }
        long ipNum = 0;
        for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++) {
            //std::cout << *it << " ";
            ipNum = ipNum * 256 + *it;
        }
        std::cout << ipNum << "\n";

        stack<int> st;
        while (num > 0) {
            st.push(num % 256);
            num /= 256;
        }
        while (st.size() > 0) {
            if (st.size() == 1) {
                std::cout << st.top() << "\n" ;
            }else
                std::cout << st.top() << ".";
            st.pop();
        }

    }
}

int main(int argc, const char * argv[]) {
    // insert code here...
    test33();

}

HJ101.输入整型数组和排序标识

输入整型数组和排序标识,对其元素按照升序或降序进行排序_牛客题霸_牛客网 (nowcoder.com)

描述 输入整型数组和排序标识,对其元素按照升序或降序进行排序 数据范围: $1 \leq n \leq 1000$ ,元素大小满足 $0 \leq v a l \leq 100000$ 输入描述: 第一行输入数组元素个数 第二行输入待排序的数组,每个数用空格隔开 第三行输入一个整数0或1。0代表升序排序,1代表降序排序 输出描述: 输出排好序的数字

示例1

输入:

8
1 2 4 9 3 55 64 25
0

输出:

1 2 3 4 9 25 55 64

示例2

输入:

5
1 2 3 4 5
1

输出:

5 4 3 2 1
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
    int N;
    while (cin >> N){

    vector <int> array(N);

    for (int i = 0; i < N; ++i)
        cin >> array[i];
    int mode;
    cin >> mode;
    sort (array.begin(), array.end());

   if (mode == 1)
       reverse (array.begin(), array.end());


       for (int i = 0; i < array.size() - 1; ++i)
        cout << array[i] << " ";
        cout << array[N-1] << endl;
    }
   return 0;    
}

*HJ106.字符串逆序

字符逆序_牛客题霸_牛客网 (nowcoder.com)

描述 将一个字符串str的内容颠倒过来,并输出。 数据范围: $1 \leq \operatorname{len}(s t r) \leq 10000$ 输入描述: 输入一个字符串,可以有空格 输出描述: 输出逆序的字符串

示例1

输入:

I am a student

复制

输出:

tneduts a ma I

复制

示例2

输入:

nowcoder

复制

输出:

redocwon

#include <iostream>
#include <string>
using namespace std;
int main(){
    string str;
    getline(cin,str);
    for(int i = str.size()-1;i>=0;i--)
        cout << str[i];
}

排序:

HJ8.合并表记录

合并表记录_牛客题霸_牛客网 (nowcoder.com)

描述

数据表记录包含表索引index和数值value(int范围的正整数),请对表索引相同的记录进行合并,即将相同索引的数值进行求和运算,输出按照index值升序进行输出。

提示:

0 <= index <= 11111111

1 <= value <= 100000

输入描述:

先输入键值对的个数n(1 <= n <= 500) 接下来n行每行输入成对的index和value值,以空格隔开

输出描述:

输出合并后的键值对(多行)

示例1

输入:

4
0 1
0 2
1 2
3 4

复制

输出:

0 3
1 2
3 4

复制

示例2

输入:

3
0 1
0 2
8 9

复制

输出:

0 3
8 9
#include<iostream>
#include<map>
using namespace std;
int main()
{
    int n;
    map<int,int> m;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        pair<int,int> tmp;
        cin>>tmp.first;
        cin>>tmp.second;
        if((m.find(tmp.first))!=m.end())
            m[tmp.first]+=tmp.second;
        else
            m[tmp.first]=tmp.second;
    }
    for(auto it=m.begin();it!=m.end();it++)
        cout<<it->first<<" "<<it->second<<endl;
    return 0;
}

*HJ14.字符串排序

字符串排序_牛客题霸_牛客网 (nowcoder.com)

描述

给定 n 个字符串,请对 n 个字符串按照字典序排列。

数据范围: $1 \leq n \leq 1000$ ,字符串长度满足 $1 \leq$ len $\leq 100$

输入描述:

输入第一行为一个正整数n(1≤n≤1000),下面n行为n个字符串(字符串长度≤100),字符串中只含有大小写字母。

输出描述:

数据输出n行,输出结果为按照字典序排列的字符串。

示例1

输入:

9
cap
to
cat
card
two
too
up
boat
boot

复制

输出:

boat
boot
cap
card
cat
to
too
two
up
#include<bits/stdc++.h>
using namespace std;
vector<string> q;     
int n;
int main(){
    cin>>n;
    string s;
    //输入n个字符串
    for(int i=0;i<n;i++){
        cin>>s;
        q.push_back(s); 
    }
    for(int i=0;i<n;i++){
            for(int j=1;j<n;j++){
                //进行比较小于就交换
                if(q[j]<q[j-1]){
                   swap(q[j],q[j-1]);
                }
            }
    }
    for(int i=0;i<n;i++) {
        cout<<q[i]<<endl;
    }
    return 0;
}

HJ27.查找兄弟单词

查找兄弟单词_牛客题霸_牛客网 (nowcoder.com)

描述 定义一个单词的“兄弟单词”为:交换该单词字母顺序(注:可以交换任意次),而不添加、删除、修改原有的字母就能生成的单词。 兄弟单词要求和原来的单词不同。例如: ab 和 ba 是兄弟单词。 ab 和 ab 则不是兄弟单词。 现在给定你 n 个单词,另外再给你一个单词 x ,让你寻找 x 的兄弟单词里,按字典序排列后的第 k 个单词是什么? 注意:字典中可能有重复单词。

数据范围: $1 \leq n \leq 1000$ ,输入的字符串长度满足 $1 \leq$ len $($ str $) \leq 10 , 1 \leq k<n$

输入描述: 输入只有一行。 先输入字典中单词的个数n,再输入n个单词作为字典单词。 然后输入一个单词x 最后后输入一个整数k 输出描述: 第一行输出查找到x的兄弟单词的个数m 第二行输出查找到的按照字典顺序排序后的第k个兄弟单词,没有符合第k个的话则不用输出。

示例1 输入: 3 abc bca cab abc 1 复制 输出: 2 bca 复制 示例2 输入: 6 cab ad abcd cba abc bca abc 1 复制 输出: 3 bca 复制 说明: abc的兄弟单词有cab cba bca,所以输出3 经字典序排列后,变为bca cab cba,所以第1个字典序兄弟单词为bca

/*
本文系「人工智能安全」(微信公众号)原创,转载请联系本文作者(同博客作者)。
欢迎你转发分享至朋友圈,并给予「关注、星标、点赞」三连支持。互相欣赏,互相批判。
我是一名有诗人气质的网络安全工程师
期待与你的思想交流碰撞出智慧的花火
水木清华
2020-03-22
查找兄弟单词
*/
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
//查找兄弟单词的函数接口,兄弟单词:单词的字母及其个数相同,但字母的排列顺序不全相同
int Search_Brother_Word(int num)
{
    string str; //字典里面的单词(小写英文字符)
    string word; //指定的单词
    vector <string> vec; //用一个向量来存储单词(形成单词字典)
    vector <string> vec_BW; //用一个向量来存储兄弟单词(形成兄弟单词字典),BW 代表 Brother Word
    int BW_index; //序号,用于查找指定单词的所有兄弟单词中序号所对应的兄弟单词(序号减一,因为从零开始)
    //输入单词,形成单词字典
    for (int i = 0; i < num; i++)
    {
        cin >> str;
        vec.push_back(str);
    }
    sort(vec.begin(), vec.end()); //输入的多个单词按字典序排列
    cin >> word; //指定单词,当然这个单词可能在、也可能不在原来的字典里面
    cin >> BW_index; //指定单词 word 的所有兄弟单词中排在第 BW_index 的单词对应序号 BW_index - 1
    //判断字典中的单词是否为指定单词的兄弟单词,若是,则将其写入兄弟单词向量 vec_BW
    string word_copy = word; //拷贝一份指定的单词,作为基准比较(字母顺序未变动)
    sort(word.begin(), word.end()); //指定的单词的字母按字典序排列
    //遍历单词字典,寻找指定单词的兄弟单词并记录在兄弟单词字典中
    for (int i = 0; i < vec.size(); i++)
    {
        //先判断字典中的单词的长度和指定单词的长度是否一致
        if (vec[i].size() == word.size())
        {
            //长度相同且字母顺序不同的单词,才可能是兄弟单词,这里反复用单词的拷贝来作为基准
            if (vec[i] != word_copy)
            {
                string copy = vec[i]; //提前拷贝一份字典中的单词,作为后续写入兄弟单词字典的样本(需要的话)
                sort(vec[i].begin(), vec[i].end()); //字典中的单词的字母按字典序排列
                //原本不相同的单词,经过字母排序后相同,才是互为兄弟单词
                if (vec[i] == word)
                {
                    vec_BW.push_back(copy);
                }
            }
        }
    }
    //分类输出结果
    //兄弟单词字典为空
    if (vec_BW.size() == 0)
    {
        cout << 0 << endl;
    }
    //兄弟单词字典不为空,但待查找的兄弟单词不存在
    else if (((vec_BW.size() > 0) && (vec_BW.size() < BW_index)) || ((vec_BW.size() > 0) && (BW_index < 1)))
    {
        cout << vec_BW.size() << endl;
    }
    //兄弟单词字典不为空,且待查找的兄弟单词存在
    else if ((vec_BW.size() > 0) && (vec_BW.size() >= BW_index) && (BW_index >= 1))
    {
        cout << vec_BW.size() << '\n' << vec_BW[BW_index - 1] << endl;
    }
    return 0;
}
//主函数
int main()
{
    int num;
    while (cin >> num)
    {
        Search_Brother_Word(num);
    }
    return 0;
}

*NC37.合并区间

合并区间_牛客题霸_牛客网 (nowcoder.com)

描述 给出一组区间,请合并所有重叠的区间。 请保证合并后的区间按区间起点升序排列。

数据范围: 区间组数 $0 \leq n \leq 2 \times 10^5$ ,区间内 的值都满足 $0 \leq$ val $\leq 2 \times 10^5$ 要求: 空间复杂度 $O(n)$ ,时间复杂度 $O(n \log n)$ 进阶:空间复杂度 $O(\mathrm{val})$ ,时间复杂度 $O(\mathrm{val})$

示例1 输入: [[10,30],[20,60],[80,100],[150,180]] 复制 返回值: [[10,60],[80,100],[150,180]] 复制 示例2 输入: [[0,10],[10,20]] 复制 返回值: [[0,20]]

class Solution {
public:
    //重载比较
    static bool cmp(Interval &a, Interval &b) { 
        return a.start < b.start;
    }

    vector<Interval> merge(vector<Interval> &intervals) {
        vector<Interval> res;
        //去除特殊情况
        if(intervals.size() == 0) 
            return res;
        //按照区间首排序
        sort(intervals.begin(), intervals.end(), cmp); 
        //放入第一个区间
        res.push_back(intervals[0]); 
        //遍历后续区间,查看是否与末尾有重叠
        for(int i = 1; i < intervals.size(); i++){ 
            //区间有重叠,更新结尾
            if(intervals[i].start <= res.back().end) 
                res.back().end = max(res.back().end, intervals[i].end);
            //区间没有重叠,直接加入
            else 
                res.push_back(intervals[i]);
        }
        return res;
    }
};

*HJ68.成绩排序

成绩排序_牛客题霸_牛客网 (nowcoder.com)

描述 给定一些同学的信息(名字,成绩)序列,请你将他们的信息按照成绩从高到低或从低到高的排列,相同成绩

都按先录入排列在前的规则处理。

例示: jack 70 peter 96 Tom 70 smith 67

从高到低 成绩 peter 96 jack 70 Tom 70 smith 67

从低到高

smith 67

jack 70

Tom 70 peter 96

注:0代表从高到低,1代表从低到高

数据范围: 人数: $1 \leq n \leq 200$ 进阶:时间复杂度: $O(n \log n)$ ,空间复杂度: $O(n)$ 输入描述: 第一行输入要排序的人的个数n,第二行输入一个整数表示排序的方式,之后n行分别输入他们的名字和成绩,以一个空格隔开

输出描述: 按照指定方式输出名字和成绩,名字和成绩之间以一个空格隔开

示例1 输入: 3 0 fang 90 yang 50 ning 70 复制 输出: fang 90 ning 70 yang 50 复制

示例2 输入: 3 1 fang 90 yang 50 ning 70 复制 输出: yang 50 ning 70 fang 90

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    int n,flag;
    while(cin>>n>>flag)
    {
        vector<pair<string,int>> res(n);
        for(int i=0;i<n;i++)
        {
        cin>>res[i].first>>res[i].second;
        }
        if(flag==0)
        {
            stable_sort(res.begin(),res.end(),[](const pair<string,int> &a,const pair<string,int> &b){
                return a.second>b.second;
            });
        }
        else if(flag==1)
        {
            stable_sort(res.begin(),res.end(),[](const pair<string,int> &a,const pair<string,int> &b){
                return a.second<b.second;
            });
        }
        for(int i=0;i<n;i++)
            cout<<res.at(i).first<<" "<<res.at(i).second<<endl;
    }
    return 0;
}
#include<bits/stdc++.h>

using namespace std;

int main() {
    int n;
    int flag;
    while (cin >> n >> flag) {
        map<int, vector<string>> mp;
        string name;
        int score;
        for(int i = 0; i < n; i++){//建立成绩和名字的映射
            cin >> name;
            cin >> score;
            mp[score].push_back(name);
        }
        if (flag == 0) {//从高到低
        for (auto it = mp.rbegin(); it != mp.rend(); ++it) {//逆序遍历
            for (int i = 0; i < it->second.size(); i++) {//成绩相同时,按照输入顺序输出
                cout << it->second[i] << " " << it->first << endl;
            }
        }
        } else {//从低到高
            for (auto it = mp.begin(); it != mp.end(); ++it) {//顺序遍历
                for (int i = 0; i < it->second.size(); i++) {//成绩相同时,按照输入顺序输出
                    cout << it->second[i] << " " << it->first << endl;
                }
            }
        }
    }
    return 0;
}

栈:

NC52.括号序列

有效括号序列_牛客题霸_牛客网 (nowcoder.com)

描述 给出一个仅包含字符'(',')','{','}','['和']',的字符串,判断给出的字符串是否是合法的括号序列 括号必须以正确的顺序关闭,"()"和"()[]{}"都是合法的括号序列,但"(]"和"([)]"不合法。

数据范围:字符串长度 $0 \leq n \leq 10000$ 要求: 空间复杂度 $O(n)$ ,时间复杂度 $O(n)$ 示例1 输入: "[" 复制 返回值: false 复制 示例2 输入: "[]" 复制 返回值: true

bool isValid(string s) {
    stack<char> stk;
    for(int i=0;i<s.size();i++){
        switch(s[i]){
            case '(':
            case '[':
            case '{':
                stk.push(s[i]);     //当前字符为'(','{','['时,元素入栈
                break;
            case ')':        
                if(stk.empty() || stk.top() != '(')    //栈空或者括号栈顶字符与当前字符不匹配,则序列为不合法序列
                    return false;
                stk.pop();                   //匹配的栈顶元素出栈
                break;
            case ']':
                if(stk.empty() || stk.top() != '[')
                    return false;
                stk.pop();
                break;
            case '}':
                if(stk.empty() || stk.top() != '{')
                    return false;
                stk.pop();
                break;
        }
    }
    return stk.empty()?true:false;      //当括号以正确顺序关闭时则最后的栈为空
}

*leetcode 1614.括号的最大嵌套深度

1614. 括号的最大嵌套深度 - 力扣(LeetCode)

如果字符串满足以下条件之一,则可以称之为 有效括号字符串(valid parentheses string,可以简写为 VPS):

字符串是一个空字符串 "",或者是一个不为 "(" 或 ")" 的单字符。 字符串可以写为 AB(A 与 B 字符串连接),其中 A 和 B 都是 有效括号字符串 。 字符串可以写为 (A),其中 A 是一个 有效括号字符串 。 类似地,可以定义任何有效括号字符串 S 的 嵌套深度 depth(S):

depth("") = 0 depth(C) = 0,其中 C 是单个字符的字符串,且该字符不是 "(" 或者 ")" depth(A + B) = max(depth(A), depth(B)),其中 A 和 B 都是 有效括号字符串 depth("(" + A + ")") = 1 + depth(A),其中 A 是一个 有效括号字符串 例如:""、"()()"、"()(()())" 都是 有效括号字符串(嵌套深度分别为 0、1、2),而 ")(" 、"(()" 都不是 有效括号字符串 。

给你一个 有效括号字符串 s,返回该字符串的 s 嵌套深度 。

示例 1:

输入:s = "(1+(2*3)+((8)/4))+1" 输出:3 解释:数字 8 在嵌套的 3 层括号中。 示例 2:

输入:s = "(1)+((2))+(((3)))" 输出:3

提示:

1 <= s.length <= 100 s 由数字 0-9 和字符 '+'、'-'、'*'、'/'、'('、')' 组成 题目数据保证括号表达式 s 是 有效的括号表达式

来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/maximum-nesting-depth-of-the-parentheses 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
public:
    int maxDepth(string s) {
        int ans = 0, size = 0;
        for (char ch : s) {
            if (ch == '(') {
                ++size;
                ans = max(ans, size);
            } else if (ch == ')') {
                --size;
            }
        }
        return ans;
    }
};

排列组合:

*leetcode 面试题08.08.有重复字符串的排列组合

面试题 08.08. 有重复字符串的排列组合 - 力扣(LeetCode)

有重复字符串的排列组合。编写一种方法,计算某字符串的所有排列组合。

示例1:

输入:S = "qqe" 输出:["eqq","qeq","qqe"] 示例2:

输入:S = "ab" 输出:["ab", "ba"] 提示:

字符都是英文字母。 字符串长度在[1, 9]之间。

来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/permutation-ii-lcci 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
public:
    void dfs(vector<string>& res, string& S, int i)
    {
        if (i == S.length())
        {
            res.push_back(S);
            return;
        }

        set<char> hash;                         //注意哈希表要在循环前创建

        for (int j = i; j < S.length(); ++ j)
        {
            if (hash.find(S[j]) == hash.end())  //对集合内不存在的字母才进行递归
            {
                hash.insert(S[j]);              //当前元素插入集合中

                swap(S[i], S[j]);       
                dfs(res, S, i + 1);
                swap(S[i], S[j]);
            }
        }
    }

    vector<string> permutation(string S) {
        vector<string> res;

        dfs(res, S, 0);

        return res;
    }
};

leetcode 77.组合

77. 组合 - 力扣(LeetCode)

给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

示例 1:

输入:n = 4, k = 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ] 示例 2:

输入:n = 1, k = 1 输出:[[1]]

提示:

1 <= n <= 20 1 <= k <= n

来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/combinations 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
public:
    vector<int> temp;
    vector<vector<int>> ans;

    vector<vector<int>> combine(int n, int k) {
        // 初始化
        // 将 temp 中 [0, k - 1] 每个位置 i 设置为 i + 1,即 [0, k - 1] 存 [1, k]
        // 末尾加一位 n + 1 作为哨兵
        for (int i = 1; i <= k; ++i) {
            temp.push_back(i);
        }
        temp.push_back(n + 1);

        int j = 0;
        while (j < k) {
            ans.emplace_back(temp.begin(), temp.begin() + k);
            j = 0;
            // 寻找第一个 temp[j] + 1 != temp[j + 1] 的位置 t
            // 我们需要把 [0, t - 1] 区间内的每个位置重置成 [1, t]
            while (j < k && temp[j] + 1 == temp[j + 1]) {
                temp[j] = j + 1;
                ++j;
            }
            // j 是第一个 temp[j] + 1 != temp[j + 1] 的位置
            ++temp[j];
        }
        return ans;
    }
};

双指针:

*leetcode 674.最长连续递增序列

674. 最长连续递增序列 - 力扣(LeetCode)

给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。

连续递增的子序列 可以由两个下标 l 和 r(l < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是连续递增子序列。

示例 1:

输入:nums = [1,3,5,4,7] 输出:3 解释:最长连续递增序列是 [1,3,5], 长度为3。 尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为 5 和 7 在原数组里被 4 隔开。

示例 2:

输入:nums = [2,2,2,2,2] 输出:1 解释:最长连续递增序列是 [2], 长度为1。

提示:

  • $1<=$ nums. length $<=10^4$
  • $-10^9<=$ nums $[i]<=10^9$

来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/longest-continuous-increasing-subsequence 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
public:
    int findLengthOfLCIS(vector<int>& nums) {
        int ans = 0;
        int n = nums.size();
        int start = 0;
        for (int i = 0; i < n; i++) {
            if (i > 0 && nums[i] <= nums[i - 1]) {
                start = i;
            }
            ans = max(ans, i - start + 1);
        }
        return ans;
    }
};

NC17.最长回文子串

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

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

数据范围: $1 \leq n \leq 1000$ 要求: 空间复杂度 $O(1)$ ,时间复杂度 $O\left(n^2\right)$ 进阶: 空间复杂度 $O(n)$ ,时间复杂度 $O(n)$

示例1 输入: "ababc" 复制 返回值: 3 复制 说明: 最长的回文子串为"aba"与"bab",长度都为3 示例2 输入: "abbba" 复制 返回值: 5 复制 示例3 输入: "b" 复制 返回值: 1

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param A string字符串 
     * @return int整型
     */
    pair<int,int> checkPalidrome(const string &A,int left,int right){
        while(left>=0&&right<A.size()&&A[left]==A[right]){
                --left,++right;
        }
        return {left+1,right-1};
    }
    int getLongestPalindrome(string A) {
        int start=0,end=0;
        // write code here
        int n_size=A.size();
        for(int i=0;i<n_size;i++){
            auto [l,r]=checkPalidrome(A, i, i);
            if(r-l>end-start){
                end=r,start=l;
            }
            auto [l1,r1]=checkPalidrome(A, i, i+1);
            if(r1-l1>end-start){
                end=r1,start=l1;
            }
        }
        return end-start+1;
    }
};

NC28.最小覆盖子串

最小覆盖子串_牛客题霸_牛客网 (nowcoder.com)

描述

给出两个字符串 s 和 t,要求在 s 中找出最短的包含 t 中所有字符的连续子串。

数据范围: $0 \leq|S|,|T| \leq 10000$ ,保证s和字符串中仅包含大小写英文字母 要求: 进阶:空间复杂度 $O(n)$ ,时间复杂度 $O(n)$ 例如: $$ \begin{aligned} &S="X D O Y E Z O D E Y X N Z" \ &T=" X Y Z " \end{aligned} $$ 找出的最短子串为" $Y X N Z "$.

注意: 如果 s 中没有包含 t 中所有字符的子串,返回空字符串 “”; 满足条件的子串可能有很多,但是题目保证满足条件的最短的子串唯一。

示例1

输入:

"XDOYEZODEYXNZ","XYZ"

复制

返回值:

"YXNZ"

复制

示例2

输入:

"abcAbA","AA"

复制

返回值:

"AbA"
class Solution {
public:
    //检查是否有小于0的
    bool check(unordered_map<char, int> &hash) { 
        for (auto iter = hash.begin(); iter != hash.end(); iter++) {
            if (iter->second < 0)
                return false;
        }
        return true;
    }
    string minWindow(string S, string T) {
        int cnt = S.length() + 1;
        //记录目标字符串T的字符个数
        unordered_map<char, int> hash; 
        for(int i = 0; i < T.length(); i++)
            //初始化哈希表都为负数,找的时候再加为正
            hash[T[i]] -= 1; 
        int slow = 0, fast = 0;  
        //记录左右区间
        int left = -1, right = -1;  
        for(; fast < S.length(); fast++){
            char c = S[fast];
            //目标字符匹配+1
            if(hash.count(c))    
            hash[c]++;
            //没有小于0的说明都覆盖了,缩小窗口
            while(check(hash)){   
                //取最优解
                if(cnt > fast - slow + 1){ 
                    cnt = fast - slow + 1;  
                    left = slow;
                    right = fast;
                }
                char c = S[slow];
                if(hash.count(c))
                    //缩小窗口的时候减1
                    hash[c]--; 
                //窗口缩小
                slow++;      
          }
      }
      //找不到的情况
      if (left == -1)     
          return "";
      return string(S.begin() + left, S.begin() + (right + 1));
  }
};

深搜:

HJ41.称砝码

称砝码_牛客题霸_牛客网 (nowcoder.com)

描述 现有n种砝码,重量互不相等,分别为 m1,m2,m3…mn ; 每种砝码对应的数量为 x1,x2,x3...xn 。现在要用这些砝码去称物体的重量(放在同一侧),问能称出多少种不同的重量。

注:

称重重量包括 0

数据范围: 每组输入数据满足 $1 \leq n \leq 10 , 1 \leq m_i \leq 2000 , 1 \leq x_i \leq 10$

输入描述: 对于每组测试数据: 第一行:n --- 砝码的种数(范围[1,10]) 第二行:m1 m2 m3 ... mn --- 每种砝码的重量(范围[1,2000]) 第三行:x1 x2 x3 .... xn --- 每种砝码对应的数量(范围[1,10])

输出描述: 利用给定的砝码可以称出的不同的重量数

示例1 输入: 2 1 2 2 1 复制 输出: 5 复制 说明: 可以表示出0,1,2,3,4五种重量。

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

int main(){
    int n;
    while(cin >> n){
        vector<int> weight(n);
        vector<int> num(n);
        int sum = 0;
        for(int i = 0; i < n; i++) //输入n种砝码重量
            cin >> weight[i];
        for(int i = 0; i < n; i++){//输入n种砝码的数量
            cin >> num[i];
            sum += num[i] * weight[i]; //砝码总重量
        }
        vector<bool> dp(sum + 1, false); //记录0到sum是否可行
        dp[0] = true;
        for(int i = 0; i < n; i++){ //遍历每一种砝码
            for(int j = 0; j < num[i]; j++){ //遍历砝码每一个数量
                for(int k = sum; k >= weight[i]; k--) //每次剩余的每个都可以添加
                    if(dp[k - weight[i]])
                        dp[k] = 1;
            }
        }
        int count = 0;
        for(int i = 0; i <= sum; i++) //找到为1的就是可以组成的质量,计数
            if(dp[i])
                count++;
        cout << count << endl;
    }
    return 0;
}

二叉树:

*leetcode 剑指offer 32 — II. 从上到下打印二叉树II

剑指 Offer 32 - II. 从上到下打印二叉树 II - 力扣(LeetCode)

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。

例如: 给定二叉树: [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回其层次遍历结果:

[ [3], [9,20], [15,7] ]

提示:

节点总数 <= 1000 注意:本题与主站 102 题相同:https://leetcode-cn.com/problems/binary-tree-level-order-traversal/

来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector <vector <int>> ret;
        if (!root) {
            return ret;
        }

        queue <TreeNode*> q;
        q.push(root);
        while (!q.empty()) {
            int currentLevelSize = q.size();
            ret.push_back(vector <int> ());
            for (int i = 1; i <= currentLevelSize; ++i) {
                auto node = q.front(); q.pop();
                ret.back().push_back(node->val);
                if (node->left) q.push(node->left);
                if (node->right) q.push(node->right);
            }
        }

        return ret;
    }
};

leetcode 剑指offer 32 — III. 从上到下打印二叉树III

剑指 Offer 32 - III. 从上到下打印二叉树 III - 力扣(LeetCode)

请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。

例如: 给定二叉树: [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回其层次遍历结果:

[ [3], [20,9], [15,7] ]

提示:

节点总数 <= 1000

来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/cong-shang-dao-xia-da-yin-er-cha-shu-iii-lcof 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int>> ans;
        if (!root) {
            return ans;
        }

        queue<TreeNode*> nodeQueue;
        nodeQueue.push(root);
        bool isOrderLeft = true;

        while (!nodeQueue.empty()) {
            deque<int> levelList;
            int size = nodeQueue.size();
            for (int i = 0; i < size; ++i) {
                auto node = nodeQueue.front();
                nodeQueue.pop();
                if (isOrderLeft) {
                    levelList.push_back(node->val);
                } else {
                    levelList.push_front(node->val);
                }
                if (node->left) {
                    nodeQueue.push(node->left);
                }
                if (node->right) {
                    nodeQueue.push(node->right);
                }
            }
            ans.emplace_back(vector<int>{levelList.begin(), levelList.end()});
            isOrderLeft = !isOrderLeft;
        }

        return ans;
    }
};

其他:

*HJ108.求最小公倍数

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

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

数据范围: $1 \leq a, b \leq 100000$ 输入描述: 输入两个正整数A和B。

输出描述: 输出A和B的最小公倍数。

示例1 输入: 5 7 复制 输出: 35 复制 示例2 输入: 2 4 复制 输出: 4

#include<iostream>
using namespace std;
int main()
{
    int a,b;
    cin>>a>>b;
    //最小公倍数一定是较大者的整数倍
    //a*b一定是a、b的公倍数,但不一定是最小的
    //所以我们从i=1,到i=min(a,b)一一遍历去寻找最小公倍数

    for(int i=1;i<=min(a,b);i++)
    {
        int beishu=i*max(a,b);
        if(beishu%a==0&&beishu%b==0)
        {
            cout<<beishu<<endl;
            break;
        }
    }
    return 0;
}

*(牛客搜索)素数

素数__牛客网 (nowcoder.com)

链接:https://www.nowcoder.com/questionTerminal/7f4be54b37a04fdaa4ee545819151114 来源:牛客网

[编程题]素数 热度指数:17478时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 64M,其他语言128M 算法知识视频讲解 输入一个整数n(2<=n<=10000),要求输出所有从1到这个整数之间(不包括1和这个整数)个位为1的素数,如果没有则输出-1。

输入描述: 输入有多组数据。 每组一行,输入n。

输出描述: 输出所有从1到这个整数之间(不包括1和这个整数)个位为1的素数(素数之间用空格隔开,最后一个素数后面没有空格),如果没有则输出-1。

示例1 输入 100 输出 11 31 41 61 71

#include<iostream>
using namespace std;
int main()
{
    int n;
    while(cin>>n)
    {
        n>11 ? cout<<11:cout<<-1;
        for(int i=31;i<n;i+=10)
        {
            for(int j=2;j*j<i;j++)
            {
                if(i%j==0)
                    break;
                else if((j+1)*(j+1)>i)
                    cout<<' '<<i;
            }
        }
        cout<<endl;
    }
}

*leetcode 994.腐烂的橘子

994. 腐烂的橘子 - 力扣(LeetCode)

在给定的 m x n 网格 grid 中,每个单元格可以有以下三个值之一:

值 0 代表空单元格; 值 1 代表新鲜橘子; 值 2 代表腐烂的橘子。 每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。

返回 直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1 。

示例 1:

img

输入:grid = [[2,1,1],[1,1,0],[0,1,1]] 输出:4 示例 2:

输入:grid = [[2,1,1],[0,1,1],[1,0,1]] 输出:-1 解释:左下角的橘子(第 2 行, 第 0 列)永远不会腐烂,因为腐烂只会发生在 4 个正向上。 示例 3:

输入:grid = [[0,2]] 输出:0 解释:因为 0 分钟时已经没有新鲜橘子了,所以答案就是 0 。

提示:

m == grid.length n == grid[i].length 1 <= m, n <= 10 grid[i][j] 仅为 0、1 或 2

来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/rotting-oranges 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
    int cnt;
    int dis[10][10];
    int dir_x[4]={0, 1, 0, -1};
    int dir_y[4]={1, 0, -1, 0};
public:
    int orangesRotting(vector<vector<int>>& grid) {
        queue<pair<int,int> >Q;
        memset(dis, -1, sizeof(dis));
        cnt = 0;
        int n=(int)grid.size(), m=(int)grid[0].size(), ans = 0;
        for (int i = 0; i < n; ++i){
            for (int j = 0; j < m; ++j){
                if (grid[i][j] == 2){
                    Q.push(make_pair(i, j));
                    dis[i][j] = 0;
                }
                else if (grid[i][j] == 1) cnt += 1;
            }
        }
        while (!Q.empty()){
            pair<int,int> x = Q.front();Q.pop();
            for (int i = 0; i < 4; ++i){
                int tx = x.first + dir_x[i];
                int ty = x.second + dir_y[i];
                if (tx < 0|| tx >= n || ty < 0|| ty >= m|| ~dis[tx][ty] || !grid[tx][ty]) continue;
                dis[tx][ty] = dis[x.first][x.second] + 1;
                Q.push(make_pair(tx, ty));
                if (grid[tx][ty] == 1){
                    cnt -= 1;
                    ans = dis[tx][ty];
                    if (!cnt) break;
                }
            }
        }
        return cnt ? -1 : ans;
    }
};

leetcode 204.计数质数

204. 计数质数 - 力扣(LeetCode)

给定整数 n ,返回 所有小于非负整数 n 的质数的数量 。

示例 1:

输入:n = 10 输出:4 解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。 示例 2:

输入:n = 0 输出:0 示例 3:

输入:n = 1 输出:0

提示:

0 <= n <= 5 * 106

来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/count-primes 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
public:
    int countPrimes(int n) {
        vector<int> primes;
        vector<int> isPrime(n, 1);
        for (int i = 2; i < n; ++i) {
            if (isPrime[i]) {
                primes.push_back(i);
            }
            for (int j = 0; j < primes.size() && i * primes[j] < n; ++j) {
                isPrime[i * primes[j]] = 0;
                if (i % primes[j] == 0) {
                    break;
                }
            }
        }
        return primes.size();
    }
};

HJ25. 数据分类处理

数据分类处理_牛客题霸_牛客网 (nowcoder.com)

描述 信息社会,有海量的数据需要分析处理,比如公安局分析身份证号码、 QQ 用户、手机号码、银行帐号等信息及活动记录。

采集输入大数据和分类规则,通过大数据分类处理程序,将大数据分类输出。

数据范围: $1 \leq I, R \leq 100 输 入 的 整 数 大 小 满 足 0 \leq v a l \leq 2^{31}-1$

输入描述: 一组输入整数序列I和一组规则整数序列R,I和R序列的第一个整数为序列的个数(个数不包含第一个整数);整数范围为0~(2^31)-1,序列个数不限

输出描述: 从R依次中取出R,对I进行处理,找到满足条件的I:

I整数对应的数字需要连续包含R对应的数字。比如R为23,I为231,那么I包含了R,条件满足 。

按R从小到大的顺序:

(1)先输出R

(2)再输出满足条件的I的个数;

(3)然后输出满足条件的I在I序列中的位置索引(从0开始);

(4)最后再输出I。

附加条件:

(1)R需要从小到大排序。相同的R只需要输出索引小的以及满足条件的I,索引大的需要过滤掉

(2)如果没有满足条件的I,对应的R不用输出

(3)最后需要在输出序列的第一个整数位置记录后续整数序列的个数(不包含“个数”本身)

序列I:15,123,456,786,453,46,7,5,3,665,453456,745,456,786,453,123(第一个15表明后续有15个整数)

序列R:5,6,3,6,3,0(第一个5表明后续有5个整数)

输出:30, 3,6,0,123,3,453,7,3,9,453456,13,453,14,123,6,7,1,456,2,786,4,46,8,665,9,453456,11,456,12,786

说明:

30----后续有30个整数

3----从小到大排序,第一个R为0,但没有满足条件的I,不输出0,而下一个R是3

6--- 存在6个包含3的I

0--- 123所在的原序号为0

123--- 123包含3,满足条件

示例1 输入: 15 123 456 786 453 46 7 5 3 665 453456 745 456 786 453 123 5 6 3 6 3 0 复制 输出: 30 3 6 0 123 3 453 7 3 9 453456 13 453 14 123 6 7 1 456 2 786 4 46 8 665 9 453456 11 456 12 786 复制 说明: 将序列R:5,6,3,6,3,0(第一个5表明后续有5个整数)排序去重后,可得0,3,6。 序列I没有包含0的元素。 序列I中包含3的元素有:I[0]的值为123、I[3]的值为453、I[7]的值为3、I[9]的值为453456、I[13]的值为453、I[14]的值为123。 序列I中包含6的元素有:I[1]的值为456、I[2]的值为786、I[4]的值为46、I[8]的值为665、I[9]的值为453456、I[11]的值为456、I[12]的值为786。 最后按题目要求的格式进行输出即可。

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

typedef unsigned long uint32; // long int 保证至少32位

int main(){
    int n;
    vector<string> I; // 用字符串存储, 便于搜索
    vector<uint32> R;
    vector<uint32> output;
    int I_sz, R_sz;

    while(cin >> I_sz){
        I.clear();
        R.clear();    // 测试用例不止一组, 因此每次都需要将I, R清空, 或者将定义挪到这里
        output.clear();

        while(I_sz--){ // 存储I
            cin >> n;
            I.push_back(to_string(n));
        }
        cin >> R_sz;
        while(R_sz--){ // 存储R
            cin >> n;
            R.push_back(n);
        }

        // R排序以及去重操作
        sort(R.begin(), R.end());
        auto unique_end = unique(R.begin(), R.end());
        R.erase(unique_end, R.end());

        for(int i = 0; i < R.size(); ++i){
            vector<uint32> tmp; // 临时vec, 如果tmp满足条件就放到output
            for(int j = 0; j < I.size(); ++j){
                if(string::npos != I[j].find(to_string(R[i]))){ // to_string() c++11支持
                    tmp.push_back(j);
                    tmp.push_back(stoul(I[j])); // stoul(), 将字符串转成 unsigned long
                }
            }
            if(!tmp.empty()){ // 在I中找到满足条件的I<j>
                output.push_back(R[i]);
                output.push_back(tmp.size() / 2); // 找到几个满足条件的I[j]
                output.insert(output.end(), tmp.begin(), tmp.end());
            }
        }

        if(!output.empty()){
            cout << output.size() << " ";
            for(int i = 0; i < output.size()-1; ++i){ // 注意最后一个数字后不跟空格, 而是换行
                cout << output[i] << " ";
            }
            cout << output[output.size()-1] << endl;
        }
    }

    return 0;
}

图森未来

作者:早睡会呢你 链接:https://www.nowcoder.com/discuss/828122 来源:牛客网

有一片海域,中间有一些小岛,找出一共有多少个「实心矩形小岛」。

海域以二维数组给出,数组中包含 0 和 1 两种元素,0 代表海,1 代表地面。被一片海包围的地面成为小岛,小岛通过水平和竖直方向与相邻的陆地连接而成。可以假设数组边缘之外都是海。 「实心矩形小岛」的定义为: 四条边与二维数组边界平行、内部均为 1 的小岛

作者:早睡会呢你 链接:https://www.nowcoder.com/discuss/828122 来源:牛客网

有 n 个物品,每个物品大小为 a[i],有 p 个背包,每个背包大小均为 k。现在你可以决定 k 的大小,问 k 最小为多小时,可以保证能将这 n 个物品放入 p 个背包内。

代码要求 实现一个函数,物品数 n、物品大小数组 a 和背包个数 p 为参数,返回背包的最小大小 k。

有n个物品 每个物品大小为a[i] 有p个背包 每个背包大小均为k 现在你可以决定k的大小 问k最小为多小时 可以保证能将这n个物品放入p个背包内

cLintCode 95 在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i]

https://blog.csdn.net/terminator_for_ever/article/details/100679641 CSDN首页 博客 下载 学习 社区 GitCode 云服务 猿如意 快速排序c语言 搜索

会员中心 足迹 动态 消息 创作中心 发布 LintCode 95 在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i]

Jackson95

于 2019-09-09 23:38:50 发布

1120 收藏 版权 class Solution { public: /** * @param m: An integer m denotes the size of a backpack * @param A: Given n items with size A[i] * @return: The maximum size */ int backPack(int m, vector &A) { // write your code here if(m==0||A.size()==0) return 0; vector<vector > dp(A.size(),vector (m+1)); for(int j=0;j<=m;j++){ dp[0][j]=A[0]<=j?A[0]:0; } for(int i=1;i<A.size();i++){ for(int j=0;j<=m;j++){ if(j>=A[i]) dp[i][j]=max(dp[i-1][j-A[i]]+A[i],dp[i-1][j]); else dp[i][j]=dp[i-1][j]; } } return dp[A.size()-1][m]; } };

Jackson95 关注

0

0 打赏

0

lintcode-92-背包问题 weixin_30629653的博客 62 92-背包问题 在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i] 注意事项 你不可以将物品进行切割。 样例 如果有4个物品[2, 3, 5, 7] 如果背包的大小为11,可以选择[2, 3, 5]装入背包,最多可以装满10的空间。 如果背包的大小为12,可以选择[2, 3, 7]装入背包,最多可以装满12的空间。 函数需要返回最多能装满的空间大小。 挑... LintCode刷题——背包问题 weixin_33953384的博客 95 背包问题: 在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i] 注意事项: 你不可以将物品进行切割。 样例: 如果有4个物品[2, 3, 5, 7] 如果背包的大小为11,可以选择[2, 3, 5]装入背包,最多可以装满10的空间。 如果背包的大小为12,可以选择[2, 3, 7]装入背包,最多可以装满12的空间。 ... (背包型动态规划)lintcode92背包问题 最新发布 weixin_46035615的博客 455 背包型动态规划 【lintcode】背包问题 Mr_health的博客 159 92. 0/1背包问题(无价值) 在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i] 样例 1: 输入: [3,4,8,5], backpack size=10 输出: 9 样例 2: 输入: [2,3,5,7], backpack size=12 输出: 12 二维的dp数组 表示对于大小为的背包,前个物品能装多满。所谓0/1背包问题,就是对于某一个物品,它有两种状态,要么放入背包,状态为1,要么不放入背包,状态为0... Lintcode 0-1背包问题 weixin_39504758的博客 141 背包问题 0-1背包问题 状态转移方程dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i - 1]] + v[i - 1]),i代表第几个物品,j代表背包容量,w[i - 1],v[i - 1]代表第i个物品的重量和价值。 #背包问题I class Solution: """ @param m: An integer m denotes the size of a backpack @param A: Given n items with s 动态规划——背包问题 努力努力再努力L 461 背包问题 目录 概述 背包问题:在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i] 背包问题:给定N个正整数:A0,A1,…An-1,一个正整数target,求有多少种组合加起来是target 背包问题:给出一个都是正整数的数组 nums,其中没有重复的数。从中找出所有的和为 target 的组合个数 背包问题:有 n 个物品和一个大小为 m 的背包,... 背包问题 guoziqing506的博客 704 题目描述:在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i] 样例: 如果有4个物品[2, 3, 5, 7] 如果背包的大小为11,可以选择[2, 3, 5]装入背包,最多可以装满10的空间。 如果背包的大小为12,可以选择[2, 3, 7]装入背包,最多可以装满12的空间。 函数需要返回最多能装满的空间大小。 背包问题是计算机科学中非 【LintCode刷题】92. 背包问题 qq_33197518的博客 194 在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i] 样例 样例 1: 输入: [3,4,8,5], backpack size=10 输出: 9 样例 2: 输入: [2,3,5,7], backpack size=12 输出: 12 挑战 O(n x m) 的时间复杂度 and O(m) 空间复杂度 如果不知道如何优化空间O(n x m) 的空间复杂度也可以通过. 思路:本题是大名鼎鼎的背包问题。动态规划来解决。 给定了背包的重量m,如果可能的话,理论上能 领扣LintCode算法问题答案-92. 背包问题 二当家的白帽子 172 领扣LintCode算法问题答案-92. 背包问题 目录92. 背包问题描述样例 1:样例 2:题解鸣谢 92. 背包问题 描述 在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i] 你不可以将物品进行切割。 样例 1: 输入: [3,4,8,5], backpack size=10 输出: 9 样例 2: 输入: [2,3,5,7], backpack size=12 输出: 12 题解 public class Solution { /. 92.背包问题 vestlee的博客 310 描述在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i]你不可以将物品进行切割。您在真实的面试中是否遇到过这个题? 是样例如果有4个物品[2, 3, 5, 7]如果背包的大小为11,可以选择[2, 3, 5]装入背包,最多可以装满10的空间。如果背包的大小为12,可以选择[2, 3, 7]装入背包,最多可以装满12的空间。函数需要返回最多能装满的空间大小。... LintCode 92.背包问题 weixin_50899769的博客 25 在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i] 动态规划+滚动数组优化 用背包容量作为纵坐标, n个物品作为纵坐标 每个点代表当前i个物品能否填满j容量 每个点都有两种可能状态 选择或不选当前行所代表的物品 由于每一行仅与其上一行的状态有关 数组可以仅保存两行信息 对所有行坐标%2 减小空间复杂度 public class Solution { /** * @param m: An integer m denotes the size of a 背包型动态规划——背包问题1 sinat_40875078的博客 85 在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i] 示例: 样例 1: 输入: [3,4,8,5], backpack size=10 输出: 9 样例 2: 输入: [2,3,5,7], backpack size=12 输出: 12 1、题目分析 首先要明确一点,在背包问题中,数组大小和总称重有关。 给定N个物品,重量分别为正整数A0, A1, …, AN-1。一个背包最大承重是M,物品的重量都是整数。每个装物品的方案的总重量都是0到M。如. 【动态规划】背包问题(组合问题,从n个物品中选k个) py今天刷题了吗 672 文章目录 模板题 划分依据 AcWing 2. 01背包问题 最后一个选还是不选 AcWing 3. 完全背包问题 最后一个选多少个 AcWing 4. 多重背包问题 最后一个选多少个 AcWing 5. 多重背包问题 II(二进制优化) 转换为01背包,把s拆成log(s)份,时间复杂度O(NMlogS) AcWing 9. 分组背包问题 最后一步选哪个 ... 动态规划之背包问题 Zero丶的专栏 103 背包问题 在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m, 每个物品的大小为A[i]. 样例 1: 输入: [3,4,8,5], backpack size=10 输出: 9 样例 2: 输入: [2,3,5,7], backpack size=12 输出: 12 解答: 定义:DP[i][j]表示有i个物品并且容量为j时,能装下的最大值。 根据第i个物品仅有2种方案: 1. 装入:此时为DP[i-1][j-A[i]] + A[i] 2. 不装入:此时为D 【LintCode】Backpack 背包问题 wutingyehe的专栏 4339 在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i]。样例 如果有4个物品[2, 3, 5, 7] 如果背包的大小为11,可以选择[2, 3, 5]装入背包,最多可以装满10的空间。 如果背包的大小为12,可以选择[2, 3, 7]装入背包,最多可以装满12的空间。 函数需要返回最多能装满的空间大小。注意 你不可以将物品进行切割。举例: 如果有4个 动态规划--背包问题 sinat_26230689的博客 1457 92. Backpack Given n items with size Ai, an integer m denotes the size of a backpack. How full you can fill this backpack? 在n个物品中挑选若干物品装入背包,最多能装多满? 【样例】 如果有4个物品[2, 3, 5, 7] 如果背包 动态规划--背包问题1 yong_zi的博客 148 92. 背包问题 在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i] 样例 如果有4个物品[2, 3, 5, 7] 如果背包的大小为11,可以选择[2, 3, 5]装入背包,最多可以装满10的空间。 如果背包的大小为12,可以选择[2, 3, 7]装入背包,最多可以装满12的空间。 函数需要返回最多能装满的空间大小。 挑战 O(n x m)... 九章算法 | 背包问题 九章算法的博客 520 在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i]。你不可以将物品进行切割。在线评测地址:LintCode 领扣样例 1: 输入: [3,4,8,5], backpack size=10 输出: 9 样例 2: 输入: [2,3,5,7], backpack size=12 输出: 12算法:DP从已知的题目中,可以总结出以下两点:每件... “相关推荐”对你有帮助么?

非常没帮助

没帮助

一般

有帮助

非常有帮助 ©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页 关于我们 招贤纳士 商务合作 寻求报道

400-660-0108

kefu@csdn.net

在线客服 工作时间 8:30-22:00 公安备案号11010502030143 京ICP备19004658号 京网文〔2020〕1039-165号 经营性网站备案信息 北京互联网违法和不良信息举报中心 家长监护 网络110报警服务 中国互联网举报中心 Chrome商店下载 账号管理规范 版权与免责声明 版权申诉 出版物许可证 营业执照 ©1999-2022北京创新乐知网络技术有限公司

Jackson95 码龄9年 暂无认证 36 原创 7万+ 周排名 190万+ 总排名 7万+ 访问

等级 823 积分 19 粉丝 7 获赞 30 评论 49 收藏 持之以恒 笔耕不辍 勤写标兵 私信 关注 搜博主文章

热门文章 WPF炫酷界面设计 40424 联想服务器System X 3650 M5 raid配置和U盘装win7系统 8857 LintCode 33 n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击(任意两个皇后不能位于同一行,同一列,同一斜线)。 4598 LintCode 90 给定n个不同的正整数,整数k以及一个目标数字。在这n个数里面找出K个数,使得这K个数的和等于目标数字,你需要找出所有满足要求的方案. 2004 LintCode 107 给定字符串 s 和单词字典 dict,确定 s 是否可以分成一个或多个以空格分隔的子串,并且这些子串都在字典中存在。 1460 分类专栏

基础编码 3篇 最新评论 WPF炫酷界面设计 m0_51023195: 大神求源码,1124031930@qq.com。不胜感激!

WPF炫酷界面设计 H Y590: 大佬求代码,2820724911@qq.com

WPF炫酷界面设计 qq_34500202: 大佬求源码,254389731@qq.com,不胜感激

有n个柱子,现在要给柱子染色,有k种颜色可以染,求有多少种染色方案 ctotalk: thanks,欢迎关注一起交流

WPF炫酷界面设计 樱落八幡: 大佬求源码,351968490@qq.com,不胜感激

您愿意向朋友推荐“博客详情页”吗?

强烈不推荐

不推荐

一般般

推荐

强烈推荐 最新文章 C++ vector 结构体排序 有n个柱子,现在要给柱子染色,有k种颜色可以染,求有多少种染色方案 1851. 购买通行证 亚历克斯计划参观博物馆,并在柜台上购买通行证。 2020年11篇2019年24篇2017年2篇

给一个数组 array 和一个数字 sum, 求这个数组的连续子数组的元素相加和 $>=\operatorname{sum}$ 解的个数。

数组元素大小:0<= array $<=10 \wedge 9$ 此如: array: $[56,21,56,35,9]$, sum $=61$ ans $=9$

给一个数组array和一个数字sum求这个数组的连续子数组的元素相加和>=sum的解的个数

未考虑右指针滑动


#include <iostream>
#include <math.h>
// #include <unodered_map>
#include <vector>

using namespace std;

int number_of_sum(vector<int> array,int sum){

//     unordered_map<int, int> static_sum;
//     static_sum[0]=1;


//     int tmp=0;
//     int counter=0;


//     for(auto &number:array){
//         tmp+=number;
//         bool result=(static_sum.find(tmp-sum)!=static_sum.end());
//         if(result){
//             counter+=static_sum[tmp-sum];
//         }


//     }
    int left=0;
    int right=0;

    int max_sum=0;

    int temp_sum=0;
    int counter=0;

    for(int i=0;i<array.size();i++){
        max_sum+=array[i];
    }

    if(max_sum<sum){
        return 0;
    }

    while(right<array.size()){
        temp_sum+=array[right];

        while(left<=right && temp_sum>=sum){
            counter+=right-left;
            temp_sum-=array[left];
            left+=1;
        }

        right+=1;

    }
    return counter;

}



int main(){
    vector<int> array={56,21,56,35,9};
    int sum=61;

    int result=number_of_sum(array,sum);
    cout<<result;
    return 0;

}

题解

int number_of_sum(vector<int> array, int sum) {
    int left = 0;
    int right = 0;

    int max_sum = 0;

    int temp_sum = 0;
    int counter = 0;

    for (int i = 0; i < array.size(); i++) {
        max_sum += array[i];
    }

    if (max_sum < sum) {
        return 0;
    }

    while (right < array.size()) {
        temp_sum += array[right];

        while (left <= right && temp_sum >= sum) {
            counter += array.size() - 1 - right + 1;
            temp_sum -= array[left];
            left += 1;
        }

        right += 1;
    }
    return counter;
}

void test() {
    vector<int> array = {56, 21, 56, 35, 9};
    int sum = 61;

    int result = number_of_sum(array, sum);
    cout << result;
    // return 0;
}

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

链接

描述

示例

接口

题解

标签

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值