【反思与总结---4】在线OJ④

it2022-05-05  153

文章目录

统计完全数个数、扑克牌大小反思:杨辉三角变形、超长整数加法反思:统计兔子、字符串通配符汽水瓶、查找两个字符串重复最大字串字符串反转、公共字串计算

统计完全数个数、扑克牌大小

题目要求:

<1>.完全数就是所有约数之和等于自身的数 <2>.给定一个数m,找出m以内所有完全数的个数

解题思路:

<1>.先写一个判断是不是完全数的函数 <2>.再写一个循环从1循环到m,是完全数就count++ <3>.输出count

代码示例:

#include<iostream> #include<vector> #include<math.h> using namespace std; bool isPerferctNum(int num) { int sum = 0; vector<int> v; for (int i = 1; i < num; ++i) { if ((num%i) == 0) { v.push_back(i); } } for (int i = 0; i < v.size(); ++i) { sum += v[i]; } if (sum == num) { return true; } return false; } int FindPerNum(int n) { int count = 0; for (int i = 0; i < n;++i) { if (isPerferctNum(i+1) == true) { count++; } } return count; } int main() { int n; while (cin >> n) { cout << FindPerNum(n) << endl; } system("pause"); return 0; }

题目要求:

<1>.输入两手牌,两手牌之间用“-”连接,每手牌的每张牌以空格分隔,“-”两边没有空格,如4 4 4 4-joker JOKER <2>.输出两手牌中较大的那手,不含连接符,扑克牌顺序不变,仍以空格隔开;如果不存在比较关系则输出ERROR

基本规则: (1)输入每手牌可能是个子,对子,顺子(连续5张),三个,炸弹(四个)和对王中的一种,不存在其他情况, 由输入保证两手牌都是合法的,顺子已经从小到大排列; (2)除了炸弹和对王可以和所有牌比较之外,其他类型的牌只能跟相同类型的存在比较关系(如,对子跟对子比 较,三个跟三个比较),不考虑拆牌情况(如:将对子拆分成个子) (3)大小规则跟大家平时了解的常见规则相同,个子,对子,三个比较牌面大小;顺子比较最小牌大小;炸弹大 于前面所有的牌,炸弹之间比较牌面大小;对王是最大的牌; (4)输入的两手牌不会出现相等的情况。 答案提示: (1)除了炸弹和对王之外,其他必须同类型比较。 (2)输入已经保证合法性,不用检查输入是否是合法的牌。 (3)输入的顺子已经经过从小到大排序,因此不用再排序了

解题思路:

<1>.各种if elseif往上堆,一条条判断… <2>.虽说已ac,但是我写的也太菜了…等答案等答案…

感觉我多写了两个else if,算了等答案再修改…

代码示例:

#include<iostream> #include<string> using namespace std; void ComPare(string& A, string& B) { string s = "345678910JQKA2"; if (A == "joker JOKER" || B == "joker JOKER") { cout << "joker JOKER" << endl; } else if (A.size() == 7 && B.size() != 7) { cout << A << endl; } else if (B.size() == 7 && A.size() != 7) { cout << B << endl; } else if ((A.size() == B.size())) { if (A == "JOKER" || B == "JOKER") { cout << "JOKER" << endl; } else if ((A == "joker"&&B != "JOKEr") || (B == "joker"&&A != "JOKER")) { cout << "joker" << endl; } if (s.find(A[0]) > s.find(B[0])) { cout << A << endl; } else { cout << B << endl; } } else if ((A.size() == 2 && B.size() == 1) || (B.size() == 2 && A.size() == 1) || (A.size() == 5 && B.size() == 3) || (B.size() == 5 && A.size() == 3)) { if (s.find(A[0]) > s.find(B[0])) { cout << A << endl; } else { cout << B << endl; } } else if (A.size() > 7 && B.size() > 7) { if (s.find(A[0]) > s.find(B[0])) { cout << A << endl; } else { cout << B << endl; } } else { cout << "ERROR" << endl; } } int main() { string s; while (getline(cin, s)) { int position = s.find('-'); string A = s.substr(0, position); string B = s.substr(position + 1); ComPare(A, B); } system("pause"); return 0; }

反思:

在gcc编译器下,对于 int i = 3; printf("%d %d", ++i, ++i),运行输出为:5 5

main() { char str[]="Geneius"; print (str); } print(char *s) { if(*s) { print(++s); printf("%c",*s); } }

下面代码的输出是suiene

考察递归, * s指向G的时候调用print,++s,s指向e…最终*s为空,递归结束,相当于从右往左打印到e

#include <iostream> using namespace std; int main(void) { const int a = 10; int * p = (int *)(&a); *p = 20; cout<<"a = "<<a<<", *p = "<<*p<<endl; return 0; }

编译器优化的结果,编译器在处理 const int a = 10;这句时 没有为a分配内存赋值

而是在加入了符号表,后续引用a时有些类似#define a 10这样处理,所以出现了同地址两个值

Widget f(Widget u) { Widget v(u); Widget w=v; return w; } main() { Widget x; Widget y=f(f(x)); }

y=f(f(x)) 有两层 f() ,为了说明过程,把里面的一层标明为 f_1 ,外面一层标明为 f_2

则 7 次调用分别是:

x -> f_1 的 u f_1 的 u -> f_1 的 v f_1 的 v -> f_1 的 w f_1 的 w -> f_2 的 u f_2 的 u -> f_2 的 v f_2 的 v -> f_2 的 w f_2 的 w -> y struct Test { Test( int ) {} Test() {} void fun() {} }; void main( void ) { Test a(1); a.fun(); Test b(); b.fun(); }

Test b();—>调用一个名为b的函数,返回值类型为Test,并不是创建了一个Test类型的对象b

#include<iostream> using namespace std; class Base { public: virtual int foo(int x) { return x * 10; } int foo(char x[14]) { return sizeof(x)+10; } }; class Derived : public Base { int foo(int x) { return x * 20; } virtual int foo(char x[10]) { return sizeof(x)+20; } }; int main() { Derived stDerived; Base *pstBase = &stDerived; char x[10]; printf("%d\n", pstBase->foo(100) + pstBase->foo(x)); return 0; }

pstBase->foo(100)调用基类的foo但是同名隐藏,所以调用的是派生类的foo,结果为2000

pstBase->foo(x),调用基类的foo,指针在32位操作系统下大小为4,所以输出2014

virtual int foo(int x),基类的虚函数

int foo(char x[14]),基类虚函数重载

virtual int foo(char x[10]),派生类自己定义的虚函数,只在派生类的子类中有用,干扰选项

<1>.牌数相同时,只需要比较第一张牌,只需要做到10把其他数字大就可以 <2>.王炸已经单独讨论了,所以牌数不同谁是炸弹输出谁 <3>.不满足比较条件的直接输出ERROR

如果做到逻辑清晰,也不是很难…

正确代码示例:

#include<iostream> #include<algorithm> #include<string> using namespace std; string ComPareCard(string S) { if (S.find("joker JOKER") != string::npos) { return "joker JOKER"; } else { int pos = S.find('-'); string A = S.substr(0, pos); string B = S.substr(pos + 1); //获取空格的个数,牌数为空格数+1 int C1 = count(A.begin(), A.end(), ' '); int C2 = count(B.begin(), B.end(), ' '); string A1 = A.substr(0, ' '); string B1 = B.substr(0, ' '); string s = "345678910JQKA2jokerJOKER"; if (C1 == C2) { cout << (s.find(C1) > s.find(C2) ? C1 : C2) << endl; } else { if (C1 == 3) { return A1; } else if (C2 == 3) { return B1; } else { return "ERROR"; } } } } int main() { string S; while (getline(cin, S)) { cout << ComPareCard(S) << endl; } system("pause"); return 0; }

杨辉三角变形、超长整数加法

题目要求:

<1>.求第N行,第一个偶数出现的位置 <2>.如果没有偶数,则输出-1

解题思路:

<1>.我一开始以为是编程题…没做出来… <2>.结果看到别人答案居然是找规律??

这样是不是不太合适…应该还是用正常的方法…等答案…

代码示例:

#include<iostream> using namespace std; int main() { int n; while (cin >> n) { if (n <= 2) { cout << -1 << endl; } else if (n % 2 != 0) { cout << 2 << endl; } else if (n % 4 == 0) { cout << 3 << endl; } else { cout << 4 << endl; } } return 0; }

题目要求:

<1>.输入两个字符串数字 <2>.输出相加后的结果,string型

解题思路:

<1>.针对长短不一的对齐问题,把短的那个补到一样长,使用resize <2>.从末尾开始相加,flag作为进位标志 <3>.相加的时候-‘0’,把相加好的结果转为char型存入C <4>.每一位相加的结果就是进位的值,比如21,进位就是2 <5>.最后把C逆置,输出C

代码示例:

#include<iostream> #include<algorithm> #include<string> using namespace std; string AddLongInt(string A, string B) { string C; if (A.size() > B.size()) { int n = A.size() - B.size(); while (n) { B.insert(B.begin(), '0'); n--; } } else { int n = B.size() - A.size(); while (n) { A.insert(A.begin(), '0'); n--; } } int flag = 0; for (int i = A.size() - 1; i >= 0; --i) { int temp = (A[i] - '0') + (B[i] - '0') + flag; C += char((temp % 10) + '0'); flag = temp / 10; } if (flag == 1) { C += '1'; } //for (auto& e : C) //{ // e += '0'; //} reverse(C.begin(),C.end()); return C; } int main() { string A; string B; while (cin >> A >> B) { cout << AddLongInt(A, B) << endl; } system("pause"); return 0; }

反思:

<1>.正确做法就是先把杨辉三角弄出来 <2>.按照题目意思,可以发现第n行有2n - 1个元素,第i,j元素等于上一行第j - 2,j - 1,j三列元素之和 <3>.每一行的第一列和最后一列都为1,如果是第二列,则只是两个元素之和 <4>.然后慢慢找,找到就输出

正确代码示例:

#include<iostream> #include<vector> using namespace std; int main() { int n, m; while (cin >> n) { m = 2 * n - 1; vector<vector<int>> v(n, vector<int>(m, 0)); v[0][0] = 1; for (int i = 1; i < n; ++i) { //第一列和最后一列都是1 v[i][0] = v[i][2 * i] = 1; for (int j = 1; j < 2 * i; ++j) { //第二列,只是两个元素的和 if (j == 1) { v[i][j] = v[i - 1][j - 1] + v[i - 1][j]; } else { //第i,j元素等于上一行第j-2,j-1,j三列元素之和 v[i][j] = v[i - 1][j - 2] + v[i - 1][j - 1] + v[i - 1][j]; } } } int k; for (k = 0; k < m; ++k) { if (v[n - 1][k] % 2 == 0 && v[n - 1][k] != 0) { cout << k + 1 << endl; break; } } if (k == m) { cout << -1 << endl; } } return 0; }

统计兔子、字符串通配符

题目要求:

<1>.一只兔子,出生之后每三个月生一只兔子,小兔子长到三个月又生一只小兔子,假设兔子都不死 <2>.输入一个int型表示月份 <3>.输出兔子总数int型

解题思路:

斐波那契数列的应用

代码示例:

#include<iostream> using namespace std; int GetCount(int n) { if(n==1||n==2) { return 1; } else { return GetCount(n-1)+GetCount(n-2); } } int main() { int n; while(cin>>n) { cout<<GetCount(n)<<endl; } return 0; }

题目要求:

<1>.输入一个带通配符的字符串在输入一个需要匹配的字符串 <2>.输出匹配结果

解题思路:

<1>.牛客网的测试用例好像不全,我第一次ac的代码我自测都有问题… <2>.之后改了一下性能变差了,但是应该是都可以匹配了… <3>.就是分情况判断…代码很垃圾…等答案…学…

代码示例:

#include<iostream> #include<string> using namespace std; bool stringMatch(string A, string B) { //te?t*.* //txt12.xls int i = 0; for (i; i < A.size(); ++i) { for (int j = 0; j < B.size(); ++j) { if (A[i] == B[j]) { i++; continue; } else if (A[i] == '?') { i++; continue; } //a.* //a.abc else if (A[i] == '*'&&i == A.size() - 1) { break; } // *.a // abc.a else if (A[i] == '*'&&A[i + 1] == '.') { i = A.find('.') + 1; j = B.find('.'); continue; } else if (A[i] == '*') { i++; continue; } else { return false; break; } } } if (i >= A.size()) { return true; } return false; } int main() { string A; string B; while (cin >> A >> B) { if (stringMatch(A, B) == true) { cout << "true" << endl; } else { cout << "false" << endl; } } system("pause"); return 0; }

汽水瓶、查找两个字符串重复最大字串

题目要求:

<1>.商店规定三个空汽水瓶可以换一瓶汽水,可以向老板借 <2>.输入文件最多包含10组测试数据,每个数据占一行,表示小张手上的空汽水瓶数 <3>.n=0表示输入结束,你的程序不应当处理这一行 <4>.对于每组测试数据,输出一行,表示最多可以喝的汽水瓶数.如果一瓶也喝不到,输出0

解题思路:

<1>.对于大佬的数学分析可得,喝的汽水数量等于瓶数/2,这种思路,太难了… <2>.使用递归求解,n == 1喝不到,n == 2只能喝一瓶 <3>.n>2的时候,return GetDrink(n-2)+1;

代码示例:

#include<iostream> using namespace std; int GetDrink(int n) { if(n==1) { return 0; } else if(n==2) { return 1; } else { return GetDrink(n-2)+1; } } int main() { int n; while(cin>>n) { if(n==0) { break; } else { cout<<GetDrink(n)<<endl; } } return 0; }

题目要求:

<1>.查找两个字符串a,b中的最长公共子串.若有多个,输出在较短串中最先出现的那个 <2>.输入两个字符串 <3>.返回重复出现的字符

解题思路:

<1>.暴力破解…从第一个字符开始逐个字符增加取子串,如果在字符串B中出现就保存起来 <2>.取子串一定要从头开始逐个增加取,如果从头开始取最大的逐个递减,找到的子串可能不是最先出现的 <3>.find的返回值是int类型,是字符串的下标,如果返回npos代表没找到 <4>.出现长度比之前保存的大的就替换 <5>.最后输出找到的子串

代码示例:

#include<iostream> #include<string> using namespace std; string FindSameString(string A, string B) { if (A.size() > B.size()) { swap(A, B); } string s; //for (int i = A.size(); i > 0; --i) for (int i = 0; i < A.size(); ++i) { //for (int j = 0; j < A.size(); ++j) for(int j = i; j<A.size(); ++j) { string tmp = A.substr(i, j - i + 1); //find返回的是字符串的下标,没找到返回npos if (B.find(tmp) == string::npos) { continue; } else if (tmp.size()>s.size()) { s = tmp; } } } return s; } int main() { string A; string B; while (cin >> A >> B) { cout << FindSameString(A, B) << endl; } system("pause"); return 0; }

字符串反转、公共字串计算

题目要求:

<1>.输入N个字符 <2>.输出反转过后的字符

解题思路:

string中提供的reverse方法

代码示例:

#include<iostream> #include<algorithm> #include<string> using namespace std; int main() { string A; while(cin>>A) { reverse(A.begin(),A.end()); cout<<A<<endl; } return 0; }

题目要求:

<1>.计算两个字符串的最大公共字串的长度,字符不区分大小写 <2>.输入两个字符串 <3>.输出一个整数

解题思路:

<1>.前面做过查找最大公共字串,这个题就是输出的不是公共字串,输出它的size <2>.暴力破解,从最大的递减查,是公共字串就保存起来,遇到更大的就替换 <3>.字符不区分大小写,所以全部转成大写

代码示例:

#include<iostream> #include<cctype> #include<string> #include<algorithm> using namespace std; int GetCommonStrLengrh(string A,string B) { transform(A.begin(),A,end(),A.begin(),towupper); transform(B.begin(),B,end(),B.begin(),towupper); string A1=A.size()<B.size()?A:B; string B1=A.size()<B.size()?B:A; string C; string tmp; for(int i=0;i<A1.size();++i) { for(j=A1.size()-1;j>=0;--j) { tmp=A1.substr(i,j); if(B1.find(tmp)!=string::npos) { if(tmp.size()>C.size()) { C=tmp; } } } } return C.size(); } int main() { string A; string B; while(cin>>A>>B) { cout<<GetCommonStrLengrh(A,B)<<endl; } return 0; }

最新回复(0)