算法题目集锦

字符串最后一个单词长度

题目

时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M 热度指数:685898

本题知识点: 字符串

题目描述
计算字符串最后一个单词的长度,单词以空格隔开。
输入描述:
一行字符串,非空,长度小于5000。

输出描述:
整数N,最后一个单词的长度。

示例1
输入
hello world
输出
5

C++

注意

  1. string不能用?

    头文件:#include "string"
    还要加上:using namespace std;

  2. 字符串长度不是length()?

    注意length()是string的成员函数。
    例如定义了string str,则需使用str.length()

    必须注意使用方法不是length(str)

第一版程序

#include "iostream"
#include "string"
using namespace std;

int main()
{
    string in;
    cin>>in;
    int len=0;//changdu
    //cout<<in.length()<<endl;//test
    for(int i=0;i<in.length();i++)
    {
        if(in[i]!= ' ')
        {
            len+=1;
        }
        else
        {
            len=0;
        }
    }
    cout<<len<<endl;
}

问题:始终只输出空格前字符的长度。
测试:使之输出字符串长度,发现仅空格前被接收。

原因:cin只能输入无空格的字符串。

方法:

  1. 对于字符数组

    int main()
    {
    	char str[100];
    	cin.getline(str,111);
    	cout<<str<<endl;
    	return 0;
    }
    

    或者

    int main()
    {
    	char str[100];
    	cin.get(str,111);//get()将换行符保留在输入序列中
    	cout<<str<<endl;
    	return 0;
    }
    
  2. 对于字符串

    int main()
    {
    	string str;
    	getline(cin,str);
    	cout<<str<<endl;
    	return 0;
    }
    

第二版程序

#include "iostream"
#include "string"
using namespace std;

int main()
{
    string in;
    //cin>>in;//直接cin是不行的
    getline(cin,in);
    int len=0;//长度
    //cout<<in.length()<<endl;
    for(int i=0;i<in.length();i++)
    {
        if(in[i]!= ' ')
        {
            len+=1;
        }
        else
        {
            len=0;
        }
    }
    cout<<len<<endl;
}

延伸阅读

  命名空间是用来组织和重用代码的编译单元。NameSpace(名字空间),是为了解决命名冲突的问题而引入的概念。通过使用 namespace xxx(就是xxx使用的范围),你所使用的库函数或变量就是在该名字空间中定义的,这样一来就不会引起不必要的冲突了。C++标准程序库中的所有标识符都被定义于一个名为std(standard)的namespace中。

  一 :<iostream><iostream.h>格式不一样,前者没有后缀。两者是两个不同的文件。后缀为.h的头文件c++标准已经明确提出不支持了。因此,当使用<iostream.h>时,相当于在c中调用库函数,使用的是全局命名空间,也就是早期的c++实现;当使用<iostream>的时候,该头文件没有定义全局命名空间,必须使用namespace std;这样才能正确使用cout。

  二: 由于namespace的概念,使用C++标准程序库的任何标识符时,可以有三种选择:

  1、直接指定标识符。例如std::ostream而不是ostream。完整语句如下: std::cout << std::hex << 3.4 << std::endl;

  2、使用using关键字。 using std::cout; using std::endl; using std::cin; 以上程序可以写成 cout << std::hex << 3.4 << endl;

  3、最方便的就是使用using namespace std; 这样命名空间std内定义的所有标识符都有效(曝光)。但这又会带来了一个新问题。无数原有的C++代码都依赖于使用了多年的伪标准库中的功能,他们都是在全局空间下的。所以就有了<iostream.h>和<iostream>等等这样的头文件,一个是为了兼容以前的C++代码,一个是为了支持新的标准。命名空间std封装的是标准程序库的名称,标准程序库为了和以前的头文件区别,一般不加".h"

可行的优化

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

学习Python

s = input()
print(len(s.split()[-1]))
# str.split(str="", num=string.count(str))
# str -- 分隔符,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等
# num -- 分割次数。默认为 -1, 即分隔所有。
# s.split()[-1]分割后的**倒数第一个**;s.split()[0]为**第一个**;s.split()[1]为**第二个**
# len() 方法返回对象(字符、列表、元组等)长度或项目个数,它是通用的,故不能用s.len()

计算字符个数

时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M 热度指数:573941

本题知识点: 字符串 哈希

题目描述

写出一个程序,接受一个由字母和数字组成的字符串,和一个字符,然后输出输入字符串中含有该字符的个数。不区分大小写。

输入描述:
第一行输入一个有字母和数字以及空格组成的字符串,第二行输入一个字符。

输出描述:
输出输入字符串中含有该字符的个数。

示例1
输入

ABCDEF
A
输出

1

使用Python

str=input()# 注意不是import,import是导入文件
s=input()
#print(len(str))
#print(s)
i=0
count=0
while i<len(str):
    if str[i].upper()==s.upper():
        count+=1# Python不支持i++、i--
    i+=1
print(count)

天坑

使用s.upper()是为了转换其大小写,也就是说可能不全是大写/小写!

改进的Python版本

  1. 小改进

    string = input()
    str1 = input()
    j = 0
    String = string.upper()
    Str1 = str1.upper()
    for i in String:
      if i == Str1:
      	j = j + 1
    print(j)
    

    for i in String:会循环字符串中的每个字符
    还可以写成:

    for i in range(len(sourceStrLower)):
      if inputStrLower == sourceStrLower[i]:
      	num += 1
      else:
      	pass
    

    range () 函数的使用是这样的:
    range(start, stop[, step]),分别是起始、终止和步长
    range(3)即:从0到3,不包含3,即0,1,2

  2. 大改进

    s = input().lower()
    s2 = input().lower()
    print(s.count(s2))
    

    S.count(sub[,start=0[,end=len(S)]])

    • sub -- 搜索的子字符串。
    • S -- 父字符串。
    • start -- 可选参数,字符串开始搜索的位置索引,默认为0。(可单独指定)
    • end -- 可选参数,字符串结束搜索的位置索引,默认为字符串的长度。(不能单独指定)

Python的一个问题

import sys
input_str=sys.stdin.readline().strip().lower()
target_char=sys.stdin.readline().strip().lower()
print(input_str.count(target_char))

sys是Python内置的一个模块。
sys.stdin.readline()提供标准输入。
strip()函数用于不接收字符串末尾的\n,如果不加上会导致结果错误。

C++再来一遍

#include "iostream"
#include "string"
using namespace std;

int main()
{
    string str;
    char c;
    getline(cin,str);
    c=getchar(); //注意单个字符的输入不能用getline()  
    int count=0;
    for(int i=0;i<str.length();i++)
    {
        if(str[i]==c)
        {
            count++;
        }
    }
    cout<<count<<endl;
}

问题自然还是出在没有转换大小写。

#include "iostream"
#include "string"
using namespace std;

string trans(string str)
{
    for(int i=0;i<str.length();i++)
    {
        if('a'<=str[i]&&'z'>=str[i])
        {
            str[i]-='a'-'A';
        }
    }
    return str;
}

char ctrans(char c)
{
    if('a'<=c&&'z'>=c)
        {
            c-='a'-'A';
        }
    return c;
}

int main()
{
    string str;
    char c;
    getline(cin,str);
    str=trans(str);
    c=getchar();
    c=ctrans(c);
    int count=0;
    for(int i=0;i<str.length();i++)
    {
        if(str[i]==c)
        {
            count++;
        }
    }
    cout<<count<<endl;
}
  • 千万别忘记retrun

  • 大小写转换里边最重要的c-='a'-'A';

C++的参考

#include <iostream>
#include <string>
 
int count_char(std::string& str, char c)
{
    std::size_t found = str.find_first_of(c);
    int count = 0;
    while (std::string::npos != found) {
        count++;
        found = str.find_first_of(c, found + 1);
    }
 
    return count;
}
 
int main(int argc, char* argv[])
{
    std::string str;
    char c = 0;
    std::getline(std::cin, str);
    std::cin >> c;
    int count = count_char(str, c);
    if (c >= 'A' && c <= 'Z') {
      count += count_char(str, c + 'a' - 'A');
    } else if (c >= 'a' && c <= 'z') {
      count += count_char(str, c + 'A' - 'a');
    }
    std::cout << count << std::endl;
    return 0;
}

高明之处在于所用的函数:

1. size_t find (const string& str, size_t pos = 0)#

str.find(str1)

说明:从pos(默认是是0,即从头开始查找)开始查找,找到第一个和str1相匹配的子串,返回该子串的起始索引位置;如果没有找到则返回string::npos
参考:find函数:http://www.cplusplus.com/reference/string/string/find/

2. size_t find_first_of (const string& str, size_t pos = 0)#

str.find_first_of(str1)

说明:从pos(默认是是0,即从头开始查找)开始查找,找到第一个和str1相匹配的子串,返回该子串的起始索引位置;如果没有找到则返回string::npos
参考:find_first_of函数:http://www.cplusplus.com/reference/string/string/find_first_of/

3.size_t find_last_of (const string& str, size_t pos = npos)#

str.find_last_of(str1)

说明:从npos(默认是字符串最后一个,即从后向前查找)开始查找,找到第一个和str1相匹配的子串,返回该子串的最后一个字符的索引位置;如果没有找到则返回string::npos
参考: find_last_of函数http://www.cplusplus.com/reference/string/string/find_last_of/

举例如下:#

Copy
#include<iostream> using namespace std;

int main(void)
{
string s = "一蓑烟雨任平生。";
int len = s.size();
int count = s.size() / string("一").size();
cout << "len = " << len << ", count = " << count << endl;
cout << "find:平: pos = " << s.find("平") << endl;
cout << "find_first_of:平: pos = " << s.find_first_of("平") << endl;
cout << "find_last_of:平: pos = " << s.find_last_of("平") << endl;
int pos = s.find("平", 9);
cout << "pos:" << pos << endl;
cout << "。: pos = " << s.find("。") << endl;
cout << "。: pos = " << s.find_last_of("。") << endl;
return 0;
}

结果:

len = 24, count = 8
find:平: pos = 15
find_first_of:平: pos = 15
find_last_of:平: pos = 17
pos:15
。: pos = 21
。: pos = 23

总结:#

C++中一个中文字符(包括汉字和中文符号)在字符串中的长度是3。在一个字符
串中查找中文字符的时候最好不要用find_last_of,因为用find_last_of返回的
是这个中文字符串的最后一个pos,而不是第一个,极容易出错。如上述例子如果
判断一句话是否是以句号结尾,如果用find_last_of进行查找会得到23而一个句
号的长度是3,加起来会大于整个字符串的长度,主要原因还是容易忘记他是子
串的最后一个pos,如果用find或者find_first_of,出错概率较低。

明明的随机数

题目

时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M 热度指数:813081

本题知识点: 数组

题目描述

明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤1000),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作(同一个测试用例里可能会有多组数据,希望大家能正确处理)。

Input Param

n 输入随机数的个数

inputArray n个随机整数组成的数组

Return Value

OutputArray 输出处理后的随机整数

注:测试用例保证输入参数的正确性,答题者无需验证。测试用例不止一组。

样例输入解释:
样例有两组测试
第一组是3个数字,分别是:2,2,1。
第二组是11个数字,分别是:10,20,40,32,67,40,20,89,300,400,15。

输入描述:
输入多行,先输入随机整数的个数,再输入相应个数的整数

输出描述:
返回多行,处理后的结果

示例1
输入
3
2
2
1
11
10
20
40
32
67
40
20
89
300
400
15
输出
1
2
10
15
20
32
40
67
89
300
400

Python

list=list()
# 注意:不能直接用list,需要先定义一个list才能用(当然也可以定义为其他名字)
# descriptor 'append' requires a 'list' object but received a 'int'
while True:# True 必须大写T
    try:# 天坑1
        # list=[0]*1000
        list.clear() # 也可以用list=[]
        num=int(input())# Python的input()都是按字符串处理,必须强制转换类型
        # print(num)
        for i in range(0,num):# 天坑2
            newnum=int((input()))
            newflag=True
            for j in range (0,len(list)):# 天坑2
                if newnum==list[j]:
                    newflag=False
            if newflag==True:
                list.append(newnum)

        #print(len(list))
        #for i in range(0,len(list)):
            #print(list[i],end=" ")
        length=len(list)
        for i in range(0,length):# 天坑2
            for j in range(i+1,length):# 天坑2
                if list[i]>list[j]:# 如果写成if(list[i]>list[j]): 也是可以运行的,但是绝不能没有:
                    cache=list[i]
                    list[i]=list[j]
                    list[j]=cache
        for i in range(0,len(list)):# 天坑2
            print(list[i])
    except:
        break

天坑1

本地调试正确后,在线还是不通过。最后发现,必须加上except:这一段才行,不然会多输出一个无用行,一直调试失败。

try:
    正常的操作
   ......................
except:
    发生异常,执行这块代码
   ......................
else:
    如果没有异常执行这块代码

天坑2

>>>for i in range(5):
...     print(i)
...
0
1
2
3
4
  • range()函数从0开始,间隔为1时,前两者均可省略。
  • range(5)不包括5!!!!

NotePad++调试Python

来自:https://www.cnblogs.com/Fengqiao/p/python_notepad.html

点击进入幕布视图浏览 https://mubu.com/doc/a8VGCUfqqw

一、使用Notepad++编辑python文件,并直接运行

  • 1.用notepad++打开python文件。或者新建文件,保存为.py格式。
  • 2.直接运行python文件
    • 按F5 。
    • 在弹出的菜单中输入:cmd /k C:\Users\Fengqiao_x\AppData\Local\Programs\Python\Python36\python.exe "$(FULL_CURRENT_PATH)"& PAUSE & EXIT 注意:路径必须是你的python路径。
    • 点击保存。输入你喜欢的名称和快捷键(选择容易记住的快捷键,并且快捷键定义不能重复)。然后点击确定。
    • 按下你刚才输入的快捷键,运行当前python文件。以后只需按快捷键便可运行python文件,不需要前面的步骤了。效果如下。

改进方法

while True:
    try:
        n = int(input())
        l = [int(input()) for _ in range(n)] ### 延伸1 延伸2
        l = sorted(set(l))# 延伸3
        # 有的更严谨一点,会加一个list(set(l)),原因是set()以后的数据类型是'set'而非'list'
        for i in l:
            print(i)
    except:
        break

延伸1,[int(input()) for _ in range(n)]

来自:https://www.isfirst.net/python/python-comprehensions

运行效果:

>>> [int(i) for i in str(123)]
[1, 2, 3]
>>> [int(i) for i in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [int(i) for i in range(1,10,2)]
[1, 3, 5, 7, 9]
>>> [int(i) for i in range(1,10,-1)]
[]
>>> [int(i) for i in range(10,1,-1)]
[10, 9, 8, 7, 6, 5, 4, 3, 2]
>>> [int(i) for i in range(10,1,-2)]
[10, 8, 6, 4, 2]
>>> i=100
>>> [int(i) for i in str(i)]
[1, 0, 0]
>>> [str(i) for i in str(i)]
['1', '0', '0']
>>> [i for i in str(i)]
['1', '0', '0']
>>> 

python的各种推导式(列表推导式、字典推导式、集合推导式):

推导式comprehensions(又称解析式),是Python的一种独有特性。推导式是可以从一个数据序列构建另一个新的数据序列的结构体。 共有三种推导,在Python2和3中都有支持:
一、列表推导式
1、使用[]生成list
基本格式

variable = [out_exp_res for out_exp in input_list if out_exp == 2]
  out_exp_res:  列表生成元素表达式,可以是有返回值的函数。
  for out_exp in input_list:  迭代input_list将out_exp传入out_exp_res表达式中。
  if out_exp == 2:  根据条件过滤哪些值可以。

例1:

multiples = [i for i in range(30) if i % 3 is 0]
print(multiples)
# Output: [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]

例2:

def squared(x):
    return x*x
multiples = [squared(i) for i in range(30) if i % 3 is 0]
print multiples
#  Output: [0, 9, 36, 81, 144, 225, 324, 441, 576, 729]

2、使用()生成generator
将俩表推导式的[]改成()即可得到生成器。

multiples = (i for i in range(30) if i % 3 is 0)
print(type(multiples))
#  Output: <type 'generator'>

二、字典推导式
字典推导和列表推导的使用方法是类似的,只不中括号该改成大括号。直接举例说明:
例子一:大小写key合并

mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
mcase_frequency = {
    k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0)
    for k in mcase.keys()
    if k.lower() in ['a','b']
}
print mcase_frequency
#  Output: {'a': 17, 'b': 34}

例子二:快速更换key和value

mcase = {'a': 10, 'b': 34}
mcase_frequency = {v: k for k, v in mcase.items()}
print mcase_frequency
#  Output: {10: 'a', 34: 'b'}

三、集合推导式
它们跟列表推导式也是类似的。 唯一的区别在于它使用大括号{}。

squared = {x**2 for x in [1, 1, 2]}
print(squared)
# Output: set([1, 4])

 

延伸2,for _ in range(n)

for _ in range(n),其中’_’ 是一个循环标志,也可以用i,j 等其他字母代替,下面的循环中不会用到,起到的是循环此数的作用
就像C语言中

延伸3,set(),sorted()

  • set() 函数创建一个无序不重复元素集,

  • sorted() 函数对所有可迭代的对象进行排序操作。

    sort 与 sorted 区别:

    • sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。

    • list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。

C++

第一版程序

#include "iostream"
using namespace std;

int main()
{
    int* array=new int[1000];//这个写法一定要记住,int* = new int[];
    while(1)
    {
        int count;
        cin>>count;//cin是>>
        for(int i=0;i<1000;i++)
        {
            array[i]=-1;
        }
        for(int i=0;i<count;i++)
        {
            int newnum;
            bool newflag=true;
            cin>>newnum;
            int setp;
            for(setp=0;array[setp]!=-1;setp++)
            {
                if(newnum==array[setp])
                    newflag=false;
            }
            if(newflag==true)
                array[setp]=newnum;
        }
        for(int i=0;array[i]!=-1;i++)
        {
            for(int j=i+1;array[j]!=-1;j++)
            {
                int cache;
                if(array[i]>array[j])
                {
                    cache=array[i];
                    array[i]=array[j];
                    array[j]=cache;
                }
            }
        }
        for(int i=0;array[i]!=-1;i++)
        {
            cout<<array[i]<<endl;
        }
    }
}

无法通过调试,提示:
运行超时:您的程序未能在规定时间内运行结束,请检查是否循环有错或算法复杂度过大。点击对比用例标准输出与你的输出

错误原因

与上面Python版类似,没有考虑到让程序结束的问题。

可正常运行的程序

#include "iostream"
using namespace std;

int main()
{
    int* array=new int[1000];
    int count;
    while(cin>>count)
    {
        for(int i=0;i<1000;i++)
        {
            array[i]=-1;
        }
        for(int i=0;i<count;i++)
        {
            int newnum;
            bool newflag=true;
            cin>>newnum;
            int setp;
            for(setp=0;array[setp]!=-1;setp++)
            {
                if(newnum==array[setp])
                    newflag=false;
            }
            if(newflag==true)
                array[setp]=newnum;
        }
        for(int i=0;array[i]!=-1;i++)
        {
            for(int j=i+1;array[j]!=-1;j++)
            {
                int cache;
                if(array[i]>array[j])
                {
                    cache=array[i];
                    array[i]=array[j];
                    array[j]=cache;
                }
            }
        }
        for(int i=0;array[i]!=-1;i++)
        {
            cout<<array[i]<<endl;
        }
    }
}

参考

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
 
vector<int> OperateInput(int sizeOfArray,vector<int> &arr)
{
    for(int i = 0;i<sizeOfArray;i++)
    {
        int cmpWait = arr[i];
        for(int j = i+1;j<sizeOfArray;j++)
        {
            if(cmpWait == arr[j])
                arr[j] = -1;
        }
    }
    vector<int> res;
    for(int i = 0;i<sizeOfArray;i++)
        if(arr[i]!=-1)
            res.push_back(arr[i]);// push_back()函数用于向容器尾加入数据
    sort(res.begin(),res.end());//sort()函数,延伸
    return res;
}
 
int main()
{
    int input1;
    while(cin>>input1)
    {
        vector<int> input2;
        int tmp;
        for(int i = 0;i<input1;i++)
        {
            cin>>tmp;
            input2.push_back(tmp);
        }
        vector<int> result = OperateInput(input1,input2);
        for(int i = 0;i<result.size();i++)
            cout<<result[i]<<endl;
    }
     
    return 0;
}

延伸,sort()函数

来自:https://www.cnblogs.com/epep/p/10959627.html

转载自博主:九江镇中https://www.cnblogs.com/jjzzx/

c++标准库里的排序函数的使用方法

I)Sort函数包含在头文件为#include<algorithm>的c++标准库中,调用标准库里的排序方法可以不必知道其内部是如何实现的,只要出现我们想要的结果即可!

II)Sort函数有三个参数:

(1)第一个是要排序的数组的起始地址。

(2)第二个是结束的地址(最后一位要排序的地址)

(3)第三个参数是排序的方法,可以是从大到小也可是从小到大,还可以不写第三个参数,此时默认的排序方法是从小到大排序。

Sort函数使用模板:

Sort(start,end,排序方法)

下面就具体使用sort()函数结合对数组里的十个数进行排序做一个说明!

例一:sort函数没有第三个参数,实现的是从小到大

复制代码
复制代码
 1 #include<iostream>
 2 
 3 #include<algorithm>
 4 using namespace std;
 5 int main()
 6 {
 7    int a[10]={9,6,3,8,5,2,7,4,1,0};
 8    for(int i=0;i<10;i++)
 9    cout<<a[i]<<endl;
10   sort(a,a+10);
11    for(int i=0;i<10;i++)
12    cout<<a[i]<<endl;
13    return 0;
14 }
复制代码
复制代码

 

例二

通过上面的例子,会产生疑问:要实现从大到小的排序肿么办?

 这就如前文所说需要在sort()函数里的第三个参数里做文章了,告诉程序我要从大到小排序!

需要加入一个比较函数 complare(),此函数的实现过程是这样的

bool complare(int a,int b)
{
    return a>b;
}

 

 

  这就是告诉程序要实现从大到小的排序的方法!

复制代码
复制代码
 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 bool complare(int a,int b)
 5 {
 6      return a>b;
 7 }
 8 int main()
 9 {
10      int a[10]={9,6,3,8,5,2,7,4,1,0};
11      for(int i=0;i<10;i++)
12      cout<<a[i]<<endl;
13      sort(a,a+10,complare);//在这里就不需要对complare函数传入参数了,
14 //这是规则
15      for(int i=0;i<10;i++)
16         cout<<a[i]<<endl;
17      return 0;
18 }
复制代码
复制代码

 假设自己定义了一个结构体node

复制代码
复制代码
1 struct node
2 {
3   int a;
4   int b;
5   double c;
6 }
复制代码
复制代码

有一个node类型的数组node arr[100],想对它进行排序:先按a值升序排列,如果a值相同,再按b值降序排列,如果b还相同,就按c降序排列。就可以写这样一个比较函数:

以下是代码片段:

复制代码
复制代码
1 bool cmp(node x,node y)
2 {
3    if(x.a!=y.a) return x.a<y.a;
4    if(x.b!=y.b) return x.b>y.b;
5    return x.c>y.c;
6 }
 
 
 
复制代码
复制代码

一个新奇的思路

#include <iostream>
using namespace std;
int main() {
    int N, n;
    while (cin >> N) {
        int a[1001] = { 0 };//延伸,C++数组的初始化
        while (N--) {
            cin >> n;
            a[n] = 1;
        }
        for (int i = 0; i < 1001; i++)
            if (a[i])
                cout << i << endl;
    }
    return 0;
}

延伸,C++数组的初始化

来自:https://www.cnblogs.com/SarahZhang0104/p/5749680.html

一、一维数组

    1. 静态 int array[100];   定义了数组array,并未对数组进行初始化
    2. 静态 int array[100] = {1,2};  定义并初始化了数组array
    3. 动态 int* array = new int[100];  delete []array;  分配了长度为100的数组array 
    4. 动态 int* array = new int[100](1,2);  delete []array; 为长度为100的数组array初始化前两个元素

 

二、二维数组

    1. 静态 int array[10][10];  定义了数组,并未初始化
    2. 静态 int array[10][10] = { {1,1} , {2,2} };  数组初始化了array[0][0,1]及array[1][0,1]
    3. 动态 int (*array)[n] = new int[m][n]; delete []array;
    4. 动态 int** array = new int*[m]; for(i) array[i] = new int[n];  for(i) delete []array[i]; delete []array;    多次析构
    5. 动态 int* array = new int[m][n];  delete []array;      数组按行存储

 

三、多维数组

  int* array = new int[m][3][4];    只有第一维可以是变量,其他维数必须是常量,否则会报错

      delete []array;       必须进行内存释放,否则内存将泄漏

 

 

四、数组作为函数形参传递

    1. 一维数组传递:
      1.   void func(int* array);
      2.   void func(int array[]);    
    2. 二维数组传递:
      1.   void func(int** array);
      2.   void func(int (*array)[n]);                  

数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针,而且在其失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。

 

 

五、字符数组

char类型的数组被常委字符数组,在字符数组中最后一位为转移字符'\0'(也被成为空字符),该字符表示字符串已结束。在C++中定义了string类,在Visual C++中定义了Cstring类。

字符串中每一个字符占用一个字节,再加上最后一个空字符。如:

char array[10] = "cnblogs";

虽然只有7个字节,但是字符串长度为8个字节。

 

也可以不用定义字符串长度,如:

char array[] = "cnblogs";

 

字符串分隔

题目

时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M 热度指数:452733
本题知识点: 字符串

题目描述
•连续输入字符串,请按长度为8拆分每个字符串后输出到新的字符串数组;
•长度不是8整数倍的字符串请在后面补数字0,空字符串不处理。
输入描述:
连续输入字符串(输入2次,每个字符串长度小于100)

输出描述:
输出到长度为8的新字符串数组

示例1
输入

abc
123456789

输出

abc00000
12345678
90000000

C++实现

#include "iostream"
#include "string"

using namespace std;

void output(string str,int len)
{
    if(len<=8)
    {
        for(int i=0;i<8;i++)
        {
            if(i<len)
                cout<<str[i];
            else
                cout<<'0';
        }
        cout<<endl;
    }
    if(len>8)
    {
        int run=len/8;
        if(len%8==0)
        {
            for(int r=0;r<run;r++)
            {
                for(int i=0;i<8;i++)
                    cout<<str[r*8+i];
                cout<<endl;
            }
        }
        else
        {
            for(int r=0;r<run;r++)
            {
                for(int i=0;i<8;i++)
                    cout<<str[r*8+i];
                cout<<endl;
            }
            for(int i=0;i<8;i++)
            {
                if(run*8+i<len)
                    cout<<str[run*8+i];
                else
                    cout<<'0';
            }
            cout<<endl;
        }
    }
}

int main()
{
    string str1,str2;
    getline(cin,str1);
    getline(cin,str2);
    int len1,len2;
    len1=str1.length();
    len2=str2.length();
    output(str1,len1);
    output(str2,len2);
}

C++的改进

#include <iostream>
 
using namespace std;
 
int main(){
    string s1, s2;
    while(getline(cin,s1)){
        getline(cin,s2);
        if(s1.empty() == 0){
            if(s1.size()%8 != 0){
                s1.insert(s1.size(),8-s1.size()%8,'0');//insert()函数
            }
            for(int ii=0;ii<s1.size();ii+=8){
                cout << s1.substr(ii,8) << endl;//substr()函数
            }
        }
        if(s2.empty() == 0){
            if(s2.size()%8 != 0){
                s2.insert(s2.size(),8-s2.size()%8,'0');
            }
            for(int ii=0;ii<s2.size();ii+=8){
                cout << s2.substr(ii,8) << endl;
            }
        }
             
    }
    return 0;
     
}

Python学习

import sys
 
 
a = sys.stdin.readline().replace('\n', '')# 延伸1
b = sys.stdin.readline().replace('\n', '')
c = [a[i:i+8] for i in range(0, len(a), 8)]# Python真是敢写就敢成
d = [b[i:i+8] for i in range(0, len(b), 8)]
z = c + d
for i in z:
    if len(i) < 8:
        x = i + (8 - len(i)) * '0'# Python真是敢写就敢成
        print(x)
    else:
        print(i)
def printStr(string):
    if len(string)<=8:
        print(string + '0'*(8-len(string)))# Python真是敢写就敢成
    else:
        while len(string)>8:
            print(string[:8])# Python真是敢写就敢成
            string = string[8:]# Python真是敢写就敢成
        print(string + '0'*(8-len(string)))
         
a = input()
b = input()
printStr(a)
printStr(b)

延伸1,sys.stdin.readline()与input()

来自:https://www.cnblogs.com/zhangyuxin/p/7203336.html

1、sys.stdin.readline( )会将标准输入全部获取,包括末尾的'\n',input()则不会。一下例子,输入  hello

import sys

line = sys.stdin.readline()

for i in range(len(line)):

  print(line[i]+'hello')

==>

hhello
ehello
lhello
lhello
ohello

hello

import sys

line = input()

for i in range(len(line)):

  print(line[i]+'hello')

==>

hhello
ehello
lhello
lhello
ohello

要想删除sys.stdin.readline( )的换行符,可以用rstrip( )函数去掉(sys.stdin.readline( ).rstrip('\n'))

sys.stdin.readline().replace('\n', '')也可以

2、sys.stdin.readline( )可以指定读取用户输入的字符长度。下面例子输入  hello

import sys

line = sys.stdin.readline(3)

print(line)

==>hel

延伸2,Python函数

def functionname( parameters ):
   "函数_文档字符串"
   function_suite
   return [expression]

十六进制转十进制

题目描述
写出一个程序,接受一个十六进制的数,输出该数值的十进制表示。(多组同时输入 )

输入描述:
输入一个十六进制的数值字符串。

输出描述:
输出该数值的十进制字符串。

示例1
输入

0xA
输出

10

学习Python

while True:# 注意,不加这套结构而出错已经不是一次了
    try:
        string = input()
        print(int(string, 16))
    except:
        break

延伸1,Python 3 进制转换

来自:https://blog.csdn.net/Gordennizaicunzai/article/details/98526859

        1、int(x, base=10),将其它进制转换成10进制。x为字符串,base的基数默认为10。有效基数是0和2-36。Base 0表示将字符串的Base解释为整数文字。

2进制转10进制:

  1. >>> int('10101010', 2)
  2. 170
  3. >>>

8进制转10进制:

  1. >>> int('252', 8)
  2. 170
  3. >>>

16进制转10进制:

  1. >>> int('0xAA', 16)
  2. 170
  3. >>>

 

        2、10进制转其它进制。

10进制转2进制:bin(number, /)。

  1. >>> bin(170)
  2. '0b10101010'
  3. >>>

10进制转8进制:oct(number, /)。

  1. >>> oct(170)
  2. '0o252'
  3. >>>

10进制转16进制:hex(number, /)。

  1. >>> hex(170)
  2. '0xaa'
  3. >>>

       

        3、bin(number, /),其它进制转2进制,返回整数的二进制表示形式。

8进制转2进制:

1)直接转:

  1. >>> bin(0o252)
  2. '0b10101010'
  3. >>>

2)8进制-->10进制-->2进制:

  1. >>> bin(int('252', 8))
  2. '0b10101010'
  3. >>>

10进制转2进制:

  1. >>> bin(170)
  2. '0b10101010'
  3. >>>

16进制转2进制:

1)直接转:

  1. >>> bin(0xaa)
  2. '0b10101010'
  3. >>>

2)16进制-->10进制-->2进制:

  1. >>> bin(int('0xaa', 16))
  2. '0b10101010'
  3. >>>

       

        4、oct(number, /),其它进制转成8进制,返回整数的八进制表示形式。

2进制转8进制:

1)直接转:

  1. >>> oct(0b10101010)
  2. '0o252'
  3. >>>

2)2进制-->10进制-->8进制:

  1. >>> oct(int('0b10101010', 2))
  2. '0o252'
  3. >>>

10进制转8进制:

  1. >>> oct(170)
  2. '0o252'
  3. >>>

16进制转8进制:

1)直接转:

  1. >>> oct(0xaa)
  2. '0o252'
  3. >>>

2)16进制-->10进制-->8进制:

  1. >>> oct(int('0xaa', 16))
  2. '0o252'
  3. >>>

 

        hex(number, /),其它进制转成16进制,返回整数的十六进制表示形式。

2进制转16进制:

1)直接转:

  1. >>> hex(0b10101010)
  2. '0xaa'
  3. >>>

2)2进制-->10进制-->16进制:

  1. >>> hex(int('0b10101010', 2))
  2. '0xaa'
  3. >>>

10进制转16进制:

  1. >>> hex(170)
  2. '0xaa'

8进制转16进制:

1)直接转:

  1. >>> hex(0o252)
  2. '0xaa'
  3. >>>

2)8进制-->10进制-->16进制:

  1. >>> hex(int('0o252', 8))
  2. '0xaa'
  3. >>>

 

学习C++

本题使用C++实现略微复杂。

较简单的实现方法

#include<iostream>
using namespace std;
int main()
{
    int n;
    while (cin >> hex >> n)
        cout << dec << n << endl;
         
    return 0;
}

较复杂的输入方法

#include <iostream>
using namespace std;
 
int main() 
{
    string str;
     
    while (getline(cin, str)) 
    {
        if (str.length() <= 0) break;
         
        long num = 0; int index = 16;
        for (int i = 2; i < str.length(); ++i) 
        {
            if (str[i] >= '0' && str[i] <= '9')
                num = num * 16 + (str[i] - '0');
            else
                num = num * 16 + (str[i] - 'A' + 10);
        }
        cout << num << endl;
    }
     
    return 0;
}

对照ASCII表理解:

质子因数(质因数分解)

题目

知识点:排序

题目描述
功能:输入一个正整数,按照从小到大的顺序输出它的所有质因子(重复的也要列举)(如180的质因子为2 2 3 3 5 )

最后一个数后面也要有空格

输入描述:
输入一个long型整数

输出描述:
按照从小到大的顺序输出它的所有质数的因子,以空格隔开。最后一个数后面也要有空格。

示例1
输入

180
输出

2 2 3 3 5

数学知识

分解质因数的方法有两种:

1、相乘法

写成几个质数相乘的形式(这些不重复的质数即为质因数),实际运算时可采用逐步分解的方式。

如:36=2233 运算时可逐步分解写成36=49=2233或312=322*3

2、短除法

从最小的质数除起,一直除到结果为质数为止。分解质因数的算式的叫短除法。

小工具

整数分解工具

请输入您需要分解的整数:

C++参考

#include <iostream>
using namespace std;
 
int main()
{
   long num;
   cin>>num;
   while(num!=1)
   {    
     for(int i=2;i<=num;i++)
     {
       if(num%i==0)
       {
          num=num/i;
          cout<<i<<' ';
          break;
       }
     }
        
   }
    
    return 0;
}

注意:这是一种巧妙的做法。

Python

Python 3 基本数据类型

https://www.runoob.com/python3/python3-data-type.html

测试程序

num=int(input())
while(num>1):
    for i in range(2,num+1):
        if num%i==0:
            print(i,end=' ')
            
            #print(num,end=' ')
            break
    num=int(num/i)# 除法后会自动变成float型

下面的程序也是没有问题的,奇怪的是在Notepad++中运行时会报错,怀疑是IDE的问题。
具体原因不明,求指教

num=int(input())
while(num>1):
    for i in range(2,num+1):
        if num%i==0:
            print(i,end=' ')
            num=int(num/i)# 除法后会自动变成float型
            #print(num,end=' ')
            break
    

Python参考

a = int(input())
def q(x):
    zhi = 1
    for i in range(2,int(x**0.5+2)):
        if x%i == 0:
            zhi = 0
            print(str(i),end = ' ')
            q(int(x/i))
            break
    if zhi == 1:
        print(str(x),end = ' ')
 
q(a)

取近似值

题目

本题知识点: 数学 语法题

题目描述
写出一个程序,接受一个正浮点数值,输出该数值的近似整数值。如果小数点后数值大于等于5,向上取整;小于5,则向下取整。

输入描述:
输入一个正浮点数值

输出描述:
输出该数值的近似整数值

示例1
输入

5.5
输出

6

Python

num=float(input())
intnum=int(num)
if num-intnum>=0.5:
    intnum+=1
print(intnum)

C++

#include "iostream"
using namespace std;

int main()
{
    float num;
    int intnum;
    
    cin>>num;
    intnum=num;//还可写成intnum=int(num);
    
    if(num-intnum>=0.5)
        intnum++;
    cout<<intnum<<endl;
}

合并表记录

本题知识点: 栈

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

输入描述:
先输入键值对的个数
然后输入成对的index和value值,以空格隔开

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

示例1
输入

4
0 1
0 2
1 2
3 4
输出

0 3
1 2
3 4

C++

#include "iostream"
#include "string"

using namespace std;

int str2int(string str)
{
    int i,t;
    i=0;
    int num=0;
    while (str[i] >= '0'&&str[i] <= '9')
	{
		t = str[i] - '0';
		num = num * 10 + t;
		i++;
	}
    return num;
}

int main()
{
    int len1;
    cin>>len1;
    
    int a[1000]={0};
    
    for(int i=0;i<=len1;i++)//???这是为何,解释1
    {
        string str;
        getline(cin,str);
        //char *p = strtok((char*)str.data(), ' ');
		//p = strtok(NULL, ' ');
        int wz=str.find(' ');
        string s1=str.substr(0,wz);
        string s2=str.substr(wz+1,str.length());
        int c1=str2int(s1);
        int c2=str2int(s2);
        
        a[c1]+=c2;
        
    }
    for(int i=0;i<1000;i++)
    {
        if(a[i]!=0)
            cout<<i<<' '<<a[i]<<endl;
    }
}

解释1

前面没有使用getline(cin,str)的缘故,以至于第一行读的不是数据的第一行。
可以如下操作:

#include "iostream"
#include "string"

using namespace std;

int str2int(string str)
{
    int i,t;
    i=0;
    int num=0;
    while (str[i] >= '0'&&str[i] <= '9')
	{
		t = str[i] - '0';
		num = num * 10 + t;
		i++;
	}
    return num;
}

int main()
{
    int len1;
    cin>>len1;
    
    int a[1000]={0};
    string str;
    getline(cin,str);
    
    for(int i=0;i<len1;i++)//???
    {
        //string str;
        getline(cin,str);
        //char *p = strtok((char*)str.data(), ' ');//为什么这个不能用,解释2
	//p = strtok(NULL, ' ');
        int wz=str.find(' ');
        string s1=str.substr(0,wz);
        string s2=str.substr(wz+1,str.length());
        int c1=str2int(s1);
        int c2=str2int(s2);
        
        a[c1]+=c2;
        
    }
    for(int i=0;i<1000;i++)
    {
        if(a[i]!=0)
            cout<<i<<' '<<a[i]<<endl;
    }
}

解释2

原因未知,在VS2013调试通过。

#include "iostream"
#include "string"

using namespace std;

int str2int(string str)
{
	int i, t;
	i = 0;
	int num = 0;
	while (str[i] >= '0'&&str[i] <= '9')
	{
		t = str[i] - '0';
		num = num * 10 + t;
		i++;
	}
	return num;
}

int main()
{
	int len1;
	cin >> len1;

	int a[1000] = { 0 };
	string str;
	getline(cin, str);

	for (int i = 0; i<len1; i++)//???
	{
		//string str;
		getline(cin, str);
		char *p = strtok((char*)str.data(), " ");
		string s1 = p;
		p = strtok(NULL, " ");
		string s2 = p;
		//int wz = str.find(' ');
		//string s1 = str.substr(0, wz);
		//string s2 = str.substr(wz + 1, str.length());
		int c1 = str2int(s1);
		int c2 = str2int(s2);

		a[c1] += c2;

	}
	for (int i = 0; i<1000; i++)
	{
		if (a[i] != 0)
			cout << i << ' ' << a[i] << endl;
	}
	system("pause");
}

延伸阅读,C++分隔字符串

来自:https://www.cnblogs.com/stonebloom-yu/p/6542756.html

原文地址:http://blog.csdn.net/xjw532881071/article/details/49154911

 

字符串切割的使用频率还是挺高的,string本身没有提供切割的方法,但可以使用stl提供的封装进行实现或者通过c函数strtok()函数实现。

1、通过stl实现

涉及到string类的两个函数find和substr: 
1、find函数 
原型:size_t find ( const string& str, size_t pos = 0 ) const; 
功能:查找子字符串第一次出现的位置。 
参数说明:str为子字符串,pos为初始查找位置。 
返回值:找到的话返回第一次出现的位置,否则返回string::npos

2、substr函数 
原型:string substr ( size_t pos = 0, size_t n = npos ) const; 
功能:获得子字符串。 
参数说明:pos为起始位置(默认为0),n为结束位置(默认为npos) 
返回值:子字符串 
代码如下:

 1 std::vector<std::string> splitWithStl(const std::string &str,const std::string &pattern)
 2 {
 3     std::vector<std::string> resVec;
 4 
 5     if ("" == str)
 6     {
 7         return resVec;
 8     }
 9     //方便截取最后一段数据
10     std::string strs = str + pattern;
11 
12     size_t pos = strs.find(pattern);
13     size_t size = strs.size();
14 
15     while (pos != std::string::npos)
16     {
17         std::string x = strs.substr(0,pos);
18         resVec.push_back(x);
19         strs = strs.substr(pos+1,size);
20         pos = strs.find(pattern);
21     }
22 
23     return resVec;
24 }
View Code

2、通过使用strtok()函数实现

原型:char *strtok(char *str, const char *delim); 
功能:分解字符串为一组字符串。s为要分解的字符串,delim为分隔符字符串。 
描述:strtok()用来将字符串分割成一个个片段。参数s指向欲分割的字符串,参数delim则为分割字符串,当strtok()在参数s的字符串中发现到参数delim的分割字符时 则会将该字符改为\0 字符。在第一次调用时,strtok()必需给予参数s字符串,往后的调用则将参数s设置成NULL。每次调用成功则返回被分割出片段的指针。

其它:strtok函数线程不安全,可以使用strtok_r替代。 
代码如下:

复制代码
vector<string> split(const string &str,const string &pattern)
{
    //const char* convert to char*
    char * strc = new char[strlen(str.c_str())+1];
    strcpy(strc, str.c_str());
    vector<string> resultVec;
    char* tmpStr = strtok(strc, pattern.c_str());
    while (tmpStr != NULL)
    {
        resultVec.push_back(string(tmpStr));
        tmpStr = strtok(NULL, pattern.c_str());
    }
</span><span style="color: #0000ff;">delete</span><span style="color: #000000;">[] strc;

</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> resultVec;

}

复制代码

 

改进方法

以上的这种方法虽然比较简单,但是中间有一个小Bug,在这里虽然可以通过所有测试,但是必须是在相同索引项最后的键值和不为0的情况下才能正确,而这里牛客的测试数据最后的输出结果的键值都是非0值,所以也通过了,但是更严谨地来应该采用一种更为常规的方法,也就是用结构体来设计算法,这样输入的每一项是一种连续存放的数据结构,相对第一种方法来说代码更复杂一点,但是更具有普适性,代码如下:

#include<iostream>
using namespace std;
struct Key_Value_Pair
{
    int index;
    int value;
};
int main()
{
    Key_Value_Pair Part[1000];
    int Key_Value_Pairs_Num,i,j,k;
    cin>>Key_Value_Pairs_Num;
    for(i=0;i<Key_Value_Pairs_Num;i++)
        cin>>Part[i].index>>Part[i].value;//cin可以连续输入数字
    for(i=0;i<Key_Value_Pairs_Num;i++)
    {
        for(j=i+1;j<Key_Value_Pairs_Num;j++)
        {
            if(Part[i].index==Part[j].index)
            {
                Part[i].value+=Part[j].value;//对第二键值求和,累加在第一次出现的键值项上,下一步进行重复索引的删除操作
                for(k=j;k<Key_Value_Pairs_Num-1;k++)
                    Part[k]=Part[k+1];
                j--;
                Key_Value_Pairs_Num--;
            }
        }
    }
    //下面进行排序操作
    Key_Value_Pair Temp;//定义一个结构体,作为交换操作的中间值
    //冒泡排序
    for(i=0;i<Key_Value_Pairs_Num-1;i++)/* 外循环为排序趟数,len个数进行len-1趟 */     
    {
        for(j=0;j<Key_Value_Pairs_Num-1-i;j++) /* 内循环为每趟比较的次数,第i趟比较len-i次 */
        {
            if(Part[j].index>Part[j+1].index)/* 相邻元素比较,若逆序则交换(升序为左大于右,降序反之) */
            {
                Temp=Part[j];
                Part[j]=Part[j+1];
                Part[j+1]=Temp;
            }
        }
    }
    for(i=0;i<Key_Value_Pairs_Num;i++)
        cout<<Part[i].index<<" "<<Part[i].value<<endl;
    return 0;
}

Python

num=int(input())
d={}
for _ in range(0,num):
    c1,c2=map(int,input().split())
    #print(c1,c2)
    if c1 in d:#python 3 没有has_key(key)这种用法
        d[c1]+=c2
    else:
        d[c1]=c2
sorted(d.keys())
for i in d:
    print(i,d[i])

另一种参考方法

import sys
while True:
    try:
        n = int(sys.stdin.readline())
        d = {}
        for i in range(n):
            k, v = map(int,sys.stdin.readline().split(' '))
            d[k] = d.setdefault(k, 0) + v
        for k in sorted(d.keys()):
            print k, str(d[k])
    except:
        break

购物单 ⭐

题目

本题知识点: 动态规划

题目描述

王强今天很开心,公司发给N元的年终奖。王强决定把年终奖用于购物,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:
主件 附件
电脑 打印机,扫描仪
书柜 图书
书桌 台灯,文具
工作椅 无

如果要买归类为附件的物品,必须先买该附件所属的主件。每个主件可以有 0 个、 1 个或 2 个附件。附件不再有从属于自己的附件。王强想买的东西很多,为了不超出预算,他把每件物品规定了一个重要度,分为 5 等:用整数 1 ~ 5 表示,第 5 等最重要。他还从因特网上查到了每件物品的价格(都是 10 元的整数倍)。他希望在不超过 N 元(可以等于 N 元)的前提下,使每件物品的价格与重要度的乘积的总和最大。

设第 j 件物品的价格为 v[j] ,重要度为 w[j] ,共选中了 k 件物品,编号依次为 j 1 , j 2 ,……, j k ,则所求的总和为:
v[j 1 ]w[j 1 ]+v[j 2 ]w[j 2 ]+ … +v[j k ]*w[j k ] 。(其中 * 为乘号)

请你帮助王强设计一个满足要求的购物单。

输入描述:
输入的第 1 行,为两个正整数,用一个空格隔开:N m

(其中 N ( <32000 )表示总钱数, m ( <60 )为希望购买物品的个数。)

从第 2 行到第 m+1 行,第 j 行给出了编号为 j-1 的物品的基本数据,每行有 3 个非负整数 v p q

(其中 v 表示该物品的价格( v<10000 ), p 表示该物品的重要度( 1 ~ 5 ), q 表示该物品是主件还是附件。如果 q=0 ,表示该物品为主件,如果 q>0 ,表示该物品为附件, q 是所属主件的编号)

输出描述:
输出文件只有一个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值( <200000 )。

示例1

输入

1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0

输出

2200

代码

#include "iostream"
using namespace std;

int main()
{
	int N, m;//N钱数
	cin >> N >> m;//m货物数

	//cout << "------------------" << endl;
	//cout << "有" << N << "钱" << m << "货" << endl;
	//cout << "------------------" << endl;

	int mm = 0;//主件数

	int *gain = new int[N + 1];
	for (int i = 1; i <= N; i++)
		gain[i] = 0;//未要求用完钱

	int **jg = new int*[m + 1];//价格
	int **zyd = new int*[m + 1];//价值=价格*重要度

	int *gx = new int[m + 1];//m与mm的对应关系

	for (int i = 1; i <= m; i++)
	{
		jg[i] = new int[3];//标记0 1 2
		zyd[i] = new int[3];//标记0 1 2
		gx[i] = 0;
		for (int j = 0; j<3; j++)
		{
			jg[i][j] = 0;
			zyd[i][j] = 0;
		}
	}

	int p, q, r;
	for (int i = 1; i <= m; i++)//数据输入过程
	{
		cin >> p >> q >> r;
		if (r == 0)
		{
			mm++;
			jg[mm][0] = p;
			zyd[mm][0] = p*q;
			gx[i] = mm;
			//cout << "------------------" << endl;
			//cout << "货物" << i << "录入为" << mm << "  价格" << jg[mm][0] << "价值" << zyd[mm][0] << endl;
			//cout << "------------------" << endl;
		}
		else
		{
			if (r != 0)
			{
				if (jg[gx[r]][1] == 0)//使用gx矩阵将原主件货号与新货号对应
				{
					jg[gx[r]][1] = p;
					zyd[gx[r]][1] = p*q;
					//cout << "------------------" << endl;
					//cout << "货物" << i << "录入为" << mm <<"的附件1  "<< "价格" << jg[mm][1] << "价值" << zyd[mm][1] << endl;
					//cout << "------------------" << endl;
				}
				else
				{
					if (jg[gx[r]][2] == 0)
					{
						jg[gx[r]][2] = p;
						zyd[gx[r]][2] = p*q;
						//cout << "------------------" << endl;
						//cout << "货物" << i << "录入为" << mm << "的附件2  " << "价格" << jg[mm][2] << "价值" << zyd[mm][2] << endl;
						//cout << "------------------" << endl;
					}
					else
						cout << "Error 1" << endl;
				}
			}
		}
	}


	for (int i = 1; i <= mm; i++)
	{
		for (int j = N; j >= jg[i][0]; j--)
		{
			if (jg[i][1] == 0)//仅有主件
            {
                if (j >= jg[i][0])
					if (gain[j]<gain[j - jg[i][0]] + zyd[i][0])
						gain[j] = gain[j - jg[i][0]] + zyd[i][0];
            }
			else
			{
				if (jg[i][2] == 0)//仅有附件1
				{
					//int temp=gain[j];
                    if (j >= jg[i][0])
						if (gain[j]<gain[j - jg[i][0]] + zyd[i][0])
							gain[j] = gain[j - jg[i][0]] + zyd[i][0];
					if (j >= jg[i][0] + jg[i][1])
						if (gain[j]<gain[j - jg[i][0] - jg[i][1]] + zyd[i][0] + zyd[i][1])
							gain[j] = gain[j - jg[i][0] - jg[i][1]] + zyd[i][0] + zyd[i][1];
				}
				else//有附件2
				{
					//int temp=gain[j];
                    if (j >= jg[i][0])
						if (gain[j]<gain[j - jg[i][0]] + zyd[i][0])
							gain[j] = gain[j - jg[i][0]] + zyd[i][0];
					if (j >= jg[i][0] + jg[i][1])
						if (gain[j]<gain[j - jg[i][0] - jg[i][1]] + zyd[i][0] + zyd[i][1])
							gain[j] = gain[j - jg[i][0] - jg[i][1]] + zyd[i][0] + zyd[i][1];
					if (j >= jg[i][0] + jg[i][2])
						if (gain[j]<gain[j - jg[i][0] - jg[i][2]] + zyd[i][0] + zyd[i][2])
							gain[j] = gain[j - jg[i][0] - jg[i][2]] + zyd[i][0] + zyd[i][2];
					if (j >= jg[i][0] + jg[i][1] + jg[i][2])
						if (gain[j]<gain[j - jg[i][0] - jg[i][1] - jg[i][2]] + zyd[i][0] + zyd[i][1] + zyd[i][2])
							gain[j] = gain[j - jg[i][0] - jg[i][1] - jg[i][2]] + zyd[i][0] + zyd[i][1] + zyd[i][2];
				}
			}
		}
	}

    
	cout << gain[N] << endl;
	system("pause");

}

题目分析

本题属于动态规划中的背包问题(分组背包),可转换为0-1背包求解。

字符串应用——密码截取

题目描述

Catcher是MCA国的情报员,他工作时发现敌国会用一些对称的密码进行通信,比如像这些ABBA,ABA,A,123321,但是他们有时会在开始或结束时加入一些无关的字符以防止别国破解。比如进行下列变化 ABBA->12ABBA,ABA->ABAKK,123321->51233214 。因为截获的串太长了,而且存在多种可能的情况(abaaab可看作是aba,或baaab的加密形式),Cathcer的工作量实在是太大了,他只能向电脑高手求助,你能帮Catcher找出最长的有效密码串吗?

输入描述:
输入一个字符串

输出描述:
返回有效密码串的最大长度

示例1
输入

ABBA

输出

4

暴力算法

def huiwen(s):
    for i in range(len(s)//2):
        if s[i]!=s[len(s)-i-1]:
            return False
    return True

while True:
    try:
        ins=input()
        maxlen=0
        for i in range(len(ins)):
            for j in range(i+1,len(ins),1):
                s=ins[i:j+1]
                if huiwen(s) and len(s)>maxlen:
                    maxlen=len(s)
        print(maxlen)
        
    except:
        break

时间复杂度过大,无法通过校验。

动态规划方法

链接:https://www.nowcoder.com/questionTerminal/3cd4621963e8454594f00199f4536bb1
来源:牛客网

#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(){
    string s;
    while(getline(cin,s))
    {
        int n=s.size();
        vector<vector<bool>> dp( n,vector<bool>(n,false) );//定义一个尺寸为n*n的二维向量并初始化为全false
        int max=1; //最长回文子串的长度初始化为1
        for(int i=0;i<n;i++)
            for(int j=0;j<=i;j++)
            {
                /*确定dp[j][i]的值*/
                if(i==j) dp[j][i]=true;
                else if(i-j==1) dp[j][i]=(s[i]==s[j]);
                else dp[j][i]=( s[j]==s[i] && dp[j+1][i-1] );
                /*若s.substr(j,i-j+1)是回文子串,更新当前最长回文子串的长度*/
                if(dp[j][i] && max<i-j+1) max=i-j+1;
            }
        cout<<max<<endl;
    }
    return 0;
}
while True:
    try:
        ins=input()
        maxlen=0
        dp=[[False for _ in range(len(ins))] for _ in range(len(ins))]
        for right in range(len(ins)):
            for left in range(right+1):
                #if right-left+1>maxlen: 注意这样是错误的,不能采取这种方法
                #原因在于,虽然此长度无计算必要,但其结果对后续计算仍有用
                if left==right:
                    dp[left][right]=True
                elif left==right-1 and ins[left]==ins[right]:
                    dp[left][right]=True
                elif ins[left]==ins[right] and dp[left+1][right-1]==True:
                    dp[left][right]=True
                if dp[left][right]==True and right-left+1>maxlen:
                    maxlen=right-left+1
                    
        print(maxlen)
        
    except:
        break

内存过限。。。

#看不懂
def check(alist):
    res=0
    n=len(alist)
    for i in range(n-1):
        #shuang shu
        if alist[i]==alist[i+1]:
            first = i
            last = i+1
            while (first>=0 and last<(n) and alist[first]==alist[last]):
                first -=1
                last +=1
            res=max(res,last-first-1)
        #dan shu
        if alist[i-1]==alist[i+1]:
            first =i-1
            last=i+1
            while (first>=0 and last<(n) and alist[first]==alist[last]):
                first -=1
                last +=1
            res=max(res,last-first-1)
    return res
while True:
    try:
        alist=input().strip()
        res=check(alist)
        print(res)
    except:
        break
#include "iostream"
#include "vector"
using namespace std;

int main()
{
    string ins;
    while(cin>>ins)
    {
        int inslen=ins.length();
        if(inslen<=1)
            cout<<1<<endl;
        else
        {
            int maxlen=0;
            
            /*bool **dp=new bool *[inslen];
            for(int i=0;i<inslen;i++)
                dp[i]=new bool [inslen];*/
            
            vector<vector<bool>> dp( inslen,vector<bool>(inslen,false) );
            
            int i,j;
            
            for(j=0;j<inslen;j++)
            {
                for(i=0;i<=j;i++)
                {
                    if(i==j)
                        dp[i][j]=true;
                    else
                    {
                        if(i==j-1&&ins[i]==ins[j])
                            dp[i][j]=true;
                        else
                        {
                            if(ins[i]==ins[j]&&dp[i+1][j-1]==true)
                                dp[i][j]=true;
                        }
                    }
                    
                    if(dp[i][j]==true&&j-i+1>maxlen)
                        maxlen=j-i+1;
                }
            }
            
            cout<<maxlen<<endl;
            
            
        }
    }
}

Manacher算法

def manacher(s):
    c ="#"
    p = c+ c.join(s)+c
    cnt = len(p)
    cus = [1]*cnt
    mx = 0
    id = 0
    for i in range(cnt):
        if i<mx:
            mirror_i = 2*id-i
            cus[i]=min(cus[mirror_i], mx-i)
        while i-cus[i] >= 0 and i+cus[i] <cnt and p[i+cus[i]] == p[i-cus[i]]:
            cus[i]+=1
        if cus[i]+i>mx:
            mx = cus[i]
            id = i
    return max(cus)-1

while True:
    try:
        s=input()
        print(manacher(s))
    except:
        break

多线程

题目描述

问题描述:有4个线程和1个公共的字符数组。线程1的功能就是向数组输出A,线程2的功能就是向字符输出B,线程3的功能就是向数组输出C,线程4的功能就是向数组输出D。要求按顺序向数组赋值ABCDABCDABCD,ABCD的个数由线程函数1的参数指定。[注:C语言选手可使用WINDOWS SDK库函数]

接口说明:

void init(); //初始化函数
void Release(); //资源释放函数
unsignedint__stdcall ThreadFun1(PVOID pM) ; //线程函数1,传入一个int类型的指针[取值范围:1 – 250,测试用例保证],用于初始化输出A次数,资源需要线程释放
unsignedint__stdcall ThreadFun2(PVOID pM) ;//线程函数2,无参数传入
unsignedint__stdcall ThreadFun3(PVOID pM) ;//线程函数3,无参数传入
Unsigned int __stdcall ThreadFunc4(PVOID pM);//线程函数4,无参数传入
char g_write[1032]; //线程1,2,3,4按顺序向该数组赋值。不用考虑数组是否越界,测试用例保证

输入描述:

输入一个int整数

输出描述:

输出多个ABCD

示例1
输入

10

输出

ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD

Python解法

C++的多线程太难记了。。。

# python 版本的多线程实现,参数是传入的

import threading
#import time

class MyThread1(threading.Thread):
     
    def __init__(self, args): 
        super(MyThread1, self).__init__()#重写__init__函数, 其中参数为self和新引入的参数
        self.args = args#固定格式, 继承父类的__init__函数
        global runcou #python3里面对全局变量只能引用不能修改,如果修改需要加上global声明
        runcou=False# 定义了一个在run()函数中使用的bool量

    def run(self):
        cou=self.args[0]#取数组中的参数
        g_write=self.args[1]
        global runcou# 引用其他地方的全局变量runcou
        if runcou==False:
            g_write.append('A')
            runcou=True
        global g_write, mutex , cou# python3里面对全局变量只能引用不能修改,如果修改需要加上global声明
        while cou>0:
            if mutex.acquire(1):
                if g_write[-1] == "D":
                    g_write.append("A")
                mutex.release()

class MyThread2(threading.Thread):
    def run(self):
        global g_write, mutex, cou
        while cou>0:
            if mutex.acquire(1):
                if g_write[-1] == "A":
                    g_write.append("B")
                mutex.release()

class MyThread3(threading.Thread):
    def run(self):
        global g_write, mutex, cou
        while cou>0:
            if mutex.acquire(1):
                if g_write[-1] == "B":
                    g_write.append("C")
                mutex.release()

class MyThread4(threading.Thread):
    def run(self):
        global g_write, mutex, cou
        while cou>0:
            if mutex.acquire(1):
                if g_write[-1] == "C":
                    g_write.append("D")
                    cou -= 1
                    if cou <= 0:
                        print(''.join(g_write))
                        mutex.release()
                        break;
                mutex.release()


while True:
    try:
        ins = int(input())
    except:
        break;
    write = []

    mutex = threading.Lock()
    tsk = []
    tsk.append(MyThread1(args=(ins,write))) 
    tsk.append(MyThread2())
    tsk.append(MyThread3())
    tsk.append(MyThread4())

    for each in tsk:
        each.start()
    for each in tsk:
        each.join()

四则运算

题目描述

请实现如下接口

/* 功能:四则运算

 * 输入:strExpression:字符串格式的算术表达式,如: "3+2*{1+2*[-4/(8-6)+7]}"

     * 返回:算术表达式的计算结果

 */

public static int calculate(String strExpression)

{

    /* 请实现*/

    return 0;

} 

约束:

pucExpression字符串中的有效字符包括[‘0’-‘9’],‘+’,‘-’, ‘*’,‘/’ ,‘(’, ‘)’,‘[’, ‘]’,‘{’ ,‘}’。

pucExpression算术表达式的有效性由调用者保证;

输入描述:

输入一个算术表达式

输出描述:

得到计算结果

示例1
输入

3+2{1+2[-4/(8-6)+7]}

输出

25

Python

据说不会Python的看到下面都哭了

#PY大法好

while True:
    try:
        '''
        a=input()
        a=a.replace("{","(")
        a=a.replace("}",")")
        a=a.replace("[","(")
        a=a.replace("]",")")
        print(int(eval(a)))
        '''
        print(eval(input()))
    except:
        break

C++

#include "iostream"
#include "string"
#include "stack"//栈头文件

using namespace std;

string change_bracket(string exp);//将大括号和中括号转成小括号,同时,将负数x转成0-x的形式
int mid_to_post(string exp);
int calculate(int a, int b, char sym);

int main()
{
    string exp;
    while (cin >> exp)
    {
        exp = change_bracket(exp);
        int exp_post = mid_to_post(exp);
        cout << exp_post << endl;
    }
    return 0;
}
//把大括号和中括号换成小括号,以便减少后期过多的判断
string change_bracket(string exp)
{
    for (int i = 0; i < exp.size(); i++)
    {
        if (exp[i] == '{' || exp[i] == '[')
            exp[i] = '(';
        if (exp[i] == '}' || exp[i] == ']')
            exp[i] = ')';
    }
     
    //cout << exp;
    return exp;
}
int mid_to_post(string exp)
{
    int flag = 0;//正负号标志,0为无正负号,1为正号,2为负号
    stack<int> exp_post;//数字栈
    stack<char> symbol;//符号栈
    for (int i = 0; i < exp.size(); i++)
    {
        char temp;
        if (isdigit(exp[i]))//为数字时
        {
            int j = i,num=0;
            while (i + 1 < exp.length() && isdigit(exp[i + 1])) 
                i++;
            string str_num = exp.substr(j, i - j+1);//从j开始截取i-j+1长的字符串
            for (int k = 0; k < str_num.size(); k++)
                num = num * 10 + str_num[k] - '0';
            if (flag == 2)
                num = 0 - num;
            flag = 0;
            exp_post.push(num);
        }  
        else if (exp[i] == '*' || exp[i] == '/' || exp[i] == '(')//为乘除时
            symbol.push(exp[i]);
        else if (exp[i] == '+'||exp[i] == '-')//为加减时
        {
            /*处理负号先*/
            if (!i || exp[i - 1]=='(')
                if (exp[i] == '+')
                    flag = 1;
                else
                    flag = 2;
 
            /*处理负号先_end*/
            while (!flag&&!symbol.empty() && symbol.top() != '(')//堆栈非空时,符号栈弹出符号,并结合数字栈计算
            {
                int b = 0, a = 0;
                char sym_temp;
                b = exp_post.top();
                exp_post.pop();
                a = exp_post.top();
                exp_post.pop();
                sym_temp = symbol.top();
                symbol.pop();
                exp_post.push(calculate(a, b, sym_temp));//计算结果入栈
            }
            if(!flag) symbol.push(exp[i]);
        }
        else if (exp[i] == ')')//为右括号时
        {
            while (symbol.top() != '(')
            {
                int b = 0, a = 0;
                char sym_temp;
                b = exp_post.top();
                exp_post.pop();
                a = exp_post.top();
                exp_post.pop();
                sym_temp = symbol.top();
                symbol.pop();
                exp_post.push(calculate(a, b, sym_temp));//计算结果入栈
            }
            symbol.pop();
        }
        else
            cout << "Input error!!!" << endl;
    }
    //循环结束后把剩下的符号弹出,并结合数字栈计算
    while (!symbol.empty())
    {
        int b = 0, a = 0;
        char sym_temp;
        b = exp_post.top();
        exp_post.pop();
        a = exp_post.top();
        exp_post.pop();
        sym_temp = symbol.top();
        symbol.pop();
        exp_post.push(calculate(a, b, sym_temp));//计算结果入栈
    }
    return exp_post.top();
}
 
int calculate(int a,int b,char sym)
{
    switch (sym)//不加break是有原因的,return之后就不执行了,加不加没影响。
    {
        case '+': return a + b;
        case '-': return a - b;
        case '*': return a * b;
        case '/': return a / b;
        default:return 0;
    }
}

我的c++代码:

#include "iostream"
#include "stack"
using namespace std;

string mod(string s)
{
    for(int i=0;i<s.length();i++)
    {
        if(s[i]=='[' || s[i]=='{')
            s[i]='(';
        else if(s[i]==']' || s[i]=='}')
            s[i]=')';
    }
    return s;
}

int camp(int a,int b,char symbol)
{
    switch(symbol)
    {
        case '+':return a+b;
        case '-':return a-b;
        case '*':return a*b;
        case '/':return a/b;
            default:return 0;
    }
}

int main()
{
    string ins;
    while(cin>>ins)
    {
        ins=mod(ins);
        stack<int> num;
        stack<char> sym;
        bool negflag=false;
        for(int i=0;i<ins.length();++i)
        {
            if(isdigit(ins[i]))//数字情况
            //用'0'<=ins[i]<='9'不行,c++不支持!!!
            {
                int j=i;//i的值不要轻易变动,危险!
                while(isdigit(ins[i+1]) && i+1<ins.length())
                    i++;
                string tempstr=ins.substr(j,i-j+1);
                int tempnum=0;
                for(int k=0;k<tempstr.length();++k)
                    tempnum=tempnum*10+tempstr[k]-'0';//不是+=啊
                if(negflag==true)
                    tempnum=0-tempnum;
                negflag=false;
                num.push(tempnum);

            }
            
            else if(ins[i]=='+' || ins[i]=='-')//加号减号
            {
                if(ins[i]=='-')//负号处理
                    if(i==0 || ins[i-1]=='(')
                        negflag=true;
                //!sym.empty() && sym.top()!='('的顺序绝对不能颠倒
                //若sym为空,先求sym.top()必然出错!!!
                while(!negflag && !sym.empty() && sym.top()!='(')//这一项的意义在于加法减法先等待其他高级运算
                {
                    int b=num.top();
                    num.pop();
                    int a=num.top();
                    num.pop();
                    char c=sym.top();
                    sym.pop();
                    num.push(camp(a,b,c));
                }
                if(!negflag)
                    sym.push(ins[i]);
            }
            
            else if(ins[i]=='*' || ins[i]=='/' || ins[i]=='(')
                sym.push(ins[i]);
            
            else if(ins[i]==')')
            {
                while(sym.top()!='(')
                {
                    int b=num.top();
                    num.pop();
                    int a=num.top();
                    num.pop();
                    char c=sym.top();
                    sym.pop();
                    num.push(camp(a,b,c));
                }
                sym.pop();//将(出栈
            }
            
            else
                cout<<"Input Error"<<endl;
        }
        
        while(!sym.empty())//这会可不一定算完了
        {
            int b=num.top();
            num.pop();
            int a=num.top();
            num.pop();
            char c=sym.top();
            sym.pop();
            num.push(camp(a,b,c));
        }
        
        cout<<num.top()<<endl;
        
    }
}
posted @ 2020-04-10 16:38  HAN_Letisl  阅读(355)  评论(0编辑  收藏  举报