【每日一题】成长必刷题

题目:解题思路:贪心算法:每次选值时都选当前能看到的局部最优解,因此只要保证每组的第二个数尽可能大具体实现:1.对数据排序2.从下标为n的元素开始,步长为2,统计每个数的和。代码实现:#include<iostream> #include<vector> #include<algorithm> using namespace std; int main() { int n; cin>>n; int size=3*n;
摘要由CSDN通过智能技术生成

1.组队竞赛(贪心)

在这里插入图片描述
解题思路:

  1. 贪心算法:每次选值时都选当前能看到的局部最优解,因此只要保证每组的第二个数尽可能大

具体实现:
1.对数据排序
2.从下标为n的元素开始,步长为2,统计每个数的和。
在这里插入图片描述
代码实现:

#include <iostream> 
#include <vector> 
#include <algorithm> 
using namespace std; 
int main() 
{
	int n; 
	cin >> n; 
	int size = 3 * n; 
	vector<int> ar(size, 0); 
	for(int i = 0;i < size; i++) 
		cin >> ar[i]; 
	sort(ar.begin(), ar.end()); 
	long long res=0; 
	for(int i = n; i < size; i += 2) 
		res += ar[i]; 
	cout << res << endl; 
	return 0; 
}

2.删除公共字符(hash)

在这里插入图片描述
解题思路:

  1. 暴力查询,依次判断字符串2的每一个字符串1中是否出现
  2. hash表,把字符串2映射到hash表中,判断字符串1

具体实现:

  1. 将第二个字符串的字符都映射到一个hashtable数组中,用来判断一个字符在这个字符串。
  2. 判断一个字符在第二个字符串,不要使用删除,这样效率太低,因为每次删除都伴随数据挪动。这里可以使用一个新字符串,最后返回新字符串

代码实现:

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string str1, str2;
    while(getline(cin, str1))
    {
        cin >> str2;
        int hash[256] = { 0 };
        for(auto i : str2)    //把str2中的元素映射到hashtable中
            hash[i] = 1;
        string res;
        for(auto i : str1)
            if(hash[i] != 1)
                res.push_back(i);
        cout << res << endl;
    }
    return 0;
}

3.排序子序列(干就完了)

在这里插入图片描述

解题思路:
定义一个变量 i 从位置 0 开始依次遍历字符串
分三种情况:

  1. 若ar[i]>ar[i+1],则进入递增序列判断,count++,i++直到下一个值大于ar[i]或者到达最后一个元素位置了
  2. 若ar[i]<ar[i+1],则进入递减序列判断,count++,i++直到下一个值小于ar[i]或者到达最后一个元素位置了
  3. 若ar[i]==ar[i+1]则 i ++

代码:

#include <iostream> 
#include <vector> 
using namespace std; 
int main() 
{ 
	int n; cin >> n; 
	vector<int> ar; 
	ar.resize(n); 
	for (int& i : ar) 
		cin >> i; 
	int res = 0; 
	int i = 0; 
	while (i < n) 
	{ 
		if (ar[i] < ar[i + 1]) 
		{
			while (i < n - 1 && ar[i] <= ar[i + 1]) //这里一定是<=,如果遇到等于也跳过 
				i++; 
			res++; 
			i++; //这里就是为什么不会越界,在查找完一次子序列之后,i++两次指向子序列下一个元素。 
		}
		else if (ar[i] > ar[i + 1]) 
		{
			while (i < n - 1 && ar[i] >= ar[i + 1]) 
				i++; 
			res++; 
			i++; 
		}
		else
			i++; //如果第一个数就是和下一个相等则
	}
	cout << res << endl; 
	return 0; 
}

4.倒置字符串(双指针切片)

在这里插入图片描述

解题思路:

  1. 双指针切片,从字符串的最后面开始往前遍历,每统计出一个字符串则切片插入
  2. 接收字符串时切片,利用cin接收到空格结束的特性,把每一片拼接起来

代码:

1.
#include <iostream>
#include <string>
using namespace std;
int main()
{
	string ar;
	getline(cin, ar);
	string res;
	int left = ar.size() - 1;
	int right = left;
	while (left >= 0)
	{
		while (left >= 0 && ar[left] != ' ')
			left--;
		res += ar.substr(left + 1, right - left);
		if (left >= 0)
			res += ' ';
		left--;
		right = left;
	}
	cout << res << endl;
	return 0;
}
2.
#include <iostream>
#include <string>
using namespace std;
// cin读取string时自动会被空格分隔开,用另一个字符串存储进行逆序输出
int main()
{
	string s1, s2;
	cin >> s2;
	while (cin >> s1)
		s2 = s1 + " " + s2;
	cout << s2 << endl;
	return 0;
}

5.字符串中找出连续最长的数字串(dp)

在这里插入图片描述

解题思路:
1.遍历字符串str,用两个字符串curres保存数字串,cur保存当前统计到的数字串,res保存每次统计的最长数字串。

代码实现:

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string res, cur, str;
    cin >> str;
    int i = 0;
    while (i < str.size())
    {
        while (i < str.size() && str[i] >= '0' && str[i] <= '9')    
            cur.push_back(str[i++]);
        if (cur.size() > res.size())
            res = cur;
        if (cur.size() != 0)
            cur.clear();
        i++;
    }
    cout << res << endl;
    return 0;
}

6.数组中出现次数超过一半的数字(dp)

在这里插入图片描述

解题思路:

  1. 数组排序后,如果符合条件的数存在,则一定是数组中间那个数。这种方法虽然容易理解,但由于涉及到快排sort,其时间复杂度为O(NlogN)并非最优;
  2. 候选人,遍历数组,用res统计数字出现最多的次数,count统计出现的次数。历下一个数字时,若它与之前保存的数字相同,则次数加1,否则次数减1;若次数为0,则保存下一个数字,并将次数置为1。遍历结束后,所保存的数字即为所求。然后再判断它是否符合条件即可

代码实现:

class Solution {
public:
	int MoreThanHalfNum_Solution(vector<int> numbers)
	{
		int res;
		int count = 0;
		for (int i : numbers)
		{
			if (count == 0)
			{
				res= i;
				count++;
			} 
				else if (i == res)
				count++;
				else
				count--;
		} 
		count = 0;
		for (int i : numbers)
			if (i == res)
				count++;
		if (count > numbers.size() / 2)
			return res;
		return 0;
	}
};

7.计算糖果

在这里插入图片描述

解题思路:
这道题的本质就是:判断三元一次方程是否有解及求解

代码:

#include<iostream>
using namespace std;
int main()
{
    int AB_ = 0;
    int BC_= 0;
    int AB = 0;
    int BC = 0;
    cin >> AB_ >> BC_ >> AB >> BC;
    int a = (AB_ + AB) / 2;
    int c = (BC - BC_) / 2;
    int b1 = (BC_ + BC) / 2;
    int b2 = (AB - AB_) / 2;
    if (b1 != b2)        //这道题核心就是检查b的值是否正确
        cout << "No" << endl;
    else
        cout << a << ' ' << b1 << ' ' << c << endl;
    return 0;
}

8.进制转换(table表的利用)

在这里插入图片描述

解题思路:
N进制数,每个进制位的值分别是X0*N^0,X1*N^1, X2*N^2X0,X1,X2就是这些进制位的值,就是就是进行取模余数就是当前低进制的位的值是多少,通过除掉进制数,进入下一个进制位的计算。

代码:

#include <iostream>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
	string s, table = "0123456789ABCDEF";
	int m, n;
	cin >> m >> n;
	bool flag = false;
	// 如果是负数,则转成正数,并标记一下
	if (m < 0)
	{
		m = 0 - m;
		flag = true;
	}
	// 按进制换算成对应的字符添加到s
	while (m)
	{
		s += table[m % n];
		m /= n;
	}
	if (flag)
		s += '-';
	reverse(s.begin(), s.end());
	cout << s << endl;
	return 0;
}

9.统计回文(双指针)

在这里插入图片描述

#include<iostream>
#include<string>
using namespace std;
bool isbackstring(string& ar)
{
	int left = 0;
	int right = ar.size() - 1;
	while (left < right)
	{
		if (ar[left] != ar[right])
			return false;
		left++;
		right--;
	} 
		return true;
} 
int main()
{
	string a, b;
	cin >> a >> b;
	int count = 0;
	for (int i = 0; i <= a.size(); i++)
	{
		string c(a);
		c.insert(i, b);
		if (isbackstring(c))
			count++;
	} 
		cout << count << endl;
	return 0;
}

10.连续最大和(dp)

在这里插入图片描述

#include<iostream>
#include<vector>
using namespace std;
int main()
{
	int num;
	cin >> num;
	vector<int> vc(num, 0);
	for (int i = 0; i < num; i++)
		cin >> vc[i];
	int res = vc[0];
	int tmp;
	for (int i : vc)
	{
		tmp += i;
		tmp = max(tmp, i);
		res = max(res, tmp);
	} 
	cout << res << endl;
	return 0;
}

11.把字符串转换成整数(细节题)

在这里插入图片描述

class Solution {
public:
    int StrToInt(string str) 
    {
        if(str.size() == 0)
            return 0;
        int flag = 1;
        int i = 0;
        if(str[i] == '+' || str[i] == '-')
        {
            if(str[i] == '-')
                flag = -1;
            i++;
        }
        int sz = str.size();
        int res = 0;
        while(i < sz)
        {
            if(str[i] < '0' || str[i] > '9')
                return 0;
            res = res * 10 + (str[i] - '0');
            i++;
        }
        return res * flag;
    }
};

12.不要二(干就完了)

在这里插入图片描述

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    int w, h;
    cin >> w >> h;
    vector<vector<int>> board(w, vector<int>(h, 1));
    int res = 0;
    for(int i = 0; i < w; i++)
    {
        for(int j = 0; j < h; j++)
        {
            if(board[i][j] == 1)
            {
                if(j + 2 < h)
                    board[i][j + 2] = 0;
                if(i + 2 < w)
                    board[i + 2][j] = 0;
                res++;
            }
        }
    }
    cout << res << endl;
    return 0;
}

13.合法括号序列(栈的使用)

在这里插入图片描述

class Parenthesis {
public:
    bool chkParenthesis(string A, int n) 
    {
        // write code here
        stack<char> stc;
        for(auto i : A)
        {
            if(i == '(')
                stc.push(i);
            else if(i == ')')
            {
                if(stc.empty())
                    return false;
                stc.pop();
            }
            else
                return false;
        }
        return stc.empty();
    }
};

14.Fibonacci数列(dp)

在这里插入图片描述

#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    int n;
    cin >> n;
    int f1 = 0, f2 = 1;
    int tmp;
    //0 1 1 2 3 5
    while(f2 < n)
    {
        tmp = f1;
        f1 = f2;
        f2 = tmp + f1;
    }
    cout << min(abs(n - f1), abs(f2 - n)) << endl;
    return 0;
}

15.两种排序方法(运算符重载)

#include <iostream>
#include <string>
#include <vector>
void isSort(vector<string>& vec, bool& fg1, bool& fg2)
{
    for(int i = 0; i < vec.size() - 1; i++)
    {
        if(vec[i] > vec[i + 1])
            fg1 = false;
        if((vec[i]).size() > (vec[i + 1]).size())
            fg2 = false;
        if(!fg1 && !fg2)
            break;
    }
}

int main()
{
    int n;
    cin >> n;
    vector<string> vec(n);
    for(auto& str : vec)
    {
        cin >> str;
    }
    bool fg1 = true, fg2 = true;
    isSort(vec, fg1, fg2);
    if(fg1 && fg2)
        cout << "both" << endl;
    else if(fg1)
        cout << "lexicographically" << endl;
    else if(fg2)
        cout << "lengths" << endl;
    else
        cout << "none" << endl;
            return 0;
}

15.最小公倍数(两种公约数求法)

在这里插入图片描述

#include <iostream>
using namespace std;

int Mindiv(int m, int n)
{
//     1.辗转相除法
//     int mod;
//     while(mod = m % n)
//     {
//         m = n;
//         n = mod;
//     }
//     return n;
//    2.更相减损法
    while(m != n)
    {
        if(m > n)
            m = m - n;
        else
            n = n - m;
    }
    return m;
    return 0;
}

int main()
{
    int num1, num2;
    cin >> num1 >> num2;
    cout << num1 * num2 / Mindiv(num1, num2) << endl;
    return 0;
}

16.走方格的方案数(dp)

在这里插入图片描述
递归:board[i][j] = board[i - 1][j] + board[i][j - 1]
如果 i 或者 j == 0 说明到达边界,边界的走法都是 1
在这里插入图片描述

#include <iostream>
using namespace std;

int WayToTar(int row, int col)
{
    if(row == 0 || col == 0)
        return 1;
    return WayToTar(row - 1, col) + WayToTar(row, col - 1);
}

int main()
{
    int row, col;
    while(cin >> row >> col)
    {
        cout << WayToTar(row, col) << endl;
    }
    return 0;
}

17.另类加法(位运算)

在这里插入图片描述
1.不进位加法:a ^ b
2.只进位加法:(a & b) << 1
3.一直循环 不进位加法 和 进位加法 ,直到进位为 0
在这里插入图片描述

class UnusualAdd {
public:
    int addAB(int A, int B) 
    {
        // write code here
        //1.先不进位相加^
        //2.再只进位相加&<<1
        //3.只要进位为0则循环结束
        while(B != 0)
        {
            int car = A ^ B;
            B = (A & B) << 1;
            A = car;
        }
        return A;
    }
};

18. 井字棋(干就完了)

在这里插入图片描述

class Board {
public:
    bool checkWon(vector<vector<int> > board) 
    {
        // write code here
        // 这个题没有捷径就是每个位置都检查一次
        int row = board.size();
        //检查每一行
        int i;
        for(i = 0; i < row; i++)
        {
            if(board[i][0] + board[i][1] + board[i][2] == row)
                return true;
        }
        //检查每一列
        for(i = 0; i < row; i++)
        {
            if(board[0][i] + board[1][i] + board[2][i] == row)
                return true;
        }
        //检查对角线
        if(board[0][0] + board[1][1] + board[2][2] == row || board[0][2] + board[1][1] + board[2][0] == row)
            return true;
        return false;
    }
};

19. 最近公共祖先(节点下标)

在这里插入图片描述

class LCA {
public:
    int getLCA(int a, int b) 
    {
        // write code here
        while(a != b)
        {
            if(a > b)
                a /= 2;
            else
                b /= 2;
        }
        return a;
    }
};

20. 求最大连续bit数(位运算)

在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
    int num;
    while(cin >> num)
    {
        int res = 0;
        int count = 0;
        while(num)
        {
            if(num & 1)    //如果num最后bit为1
            {
                count++;
                res = max(res, count);
            }
            else
                count = 0;
            num >>= 1;
        }
        cout << res << endl;
    }
    return 0;
}

21.二进制插入 -》(位运算)

在这里插入图片描述

1. 这里保证了 i-j+1 必定是 0
class BinInsert {
public:
    int binInsert(int n, int m, int j, int i) 
    {
        // write code here
        return n | m << j;
    }
};
2. 如果不保证 i-j+10
class BinInsert {
public:
    int binInsert(int n, int m, int j, int i) 
    {
        // write code here
        int tmp = m;
        int setZero = 0;
        while(tmp)
        {
            setZero <<= 1;
            setZero |= 1;
            tmp >>= 1;
        }
        for(; tmp < j; tmp++)
        {
            setZero <<= 1;
            m <<= 1;
        }
        return n & (~setZero) | m;
    }
};

22.组成偶数最近的素数 -》(质数的求法)

在这里插入图片描述

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

bool isPrm(int tar)
{
    int tmp = sqrt(tar);
    for (int i = 2; i <= tmp; i++)
    {
        if(tar % i == 0)
            return false;
    }
    return true;
}

int main()
{
    int n;
    while (cin >> n)
    {
        for(int i = n / 2; i > 0; --i)
        {
            if(isPrm(i) && isPrm(n - i))
            {
                cout << i << endl << n - i << endl;
                break;
            }
        }
    }
    return 0;
}

23.参数解析(遍历)

在这里插入图片描述

https://www.nowcoder.com/practice/668603dc307e4ef4bb07bcd0615ea677?tpId=37&&tqId=21297&rp=1&ru=/activity/oj&qru=/ta/huawei/question-ranking

#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
    string str;
    getline(cin, str);
    vector<string> vec;
    string tmp;
    for(int i = 0; i < str.size(); i++)
    {
        if(str[i] != ' ' && str[i] != '"')
            tmp.push_back(str[i]);
        else
        {
            if(str[i] == ' ' && !tmp.empty())
                vec.push_back(tmp);
            else
            {
                i++;
                while(i < str.size() && str[i] != '"')
                {
                    tmp.push_back(str[i]);
                    i++;
                }
                i++;
                vec.push_back(tmp);
            }
            tmp.clear();
        }
    }
    if(!tmp.empty())
        vec.push_back(tmp);
    cout << vec.size() << endl;
    for(auto it : vec)
        cout << it << endl;
    return 0;
}

24.跳石板(dp)

在这里插入图片描述
解题:找到状态方程:dp[i + p] = min(dp[i] + 1, dp[i + p])意思是:dp[i + p] 位置的值等于dp[i] 的值再跳一步。其中 p 是 i 的一个约数。如果dp[i + p] 为 0 ,则dp[i + p] = dp[i] + 1

https://www.nowcoder.com/practice/4284c8f466814870bae7799a07d49ec8?tpId=85&&tqId=29852&rp=1&ru=/activity/oj&qru=/ta/2017test/question-ranking

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    int N, M;
    cin >> N >> M;
    vector<int> dp(M + 1, 0);
    dp[N] = 1;
    for(int i = N; i < M; i++)
    {
        if(dp[i] == 0)                    //如果当前石板为0,则说明不可能从该跳板往后跳
            continue;
        for(int j = 2; j <= sqrt(i); j++)
        {
            if(i % j == 0)                // 如果是约数则进行
            {
                int num1 = i + j;        // 约数中较小数
                int num2 = i + i / j;    // 约数中较大数
                if(num1 > M)             // 若较小数都大于M则直接跳出
                    break;
                if(dp[num1] == 0)
                    dp[num1] = dp[i] + 1;
                else
                    dp[num1] = min(dp[num1], dp[i] + 1);
                if(num2 <= M)
                {
                    if(dp[num2] == 0)
                        dp[num2] = dp[i] + 1;
                    else
                        dp[num2] = min(dp[num2], dp[i] + 1);
                }
            }
        }
    }
    cout << dp[M] - 1 << endl;
    return 0;
}

25.计算日期到天数转换(做就完了)

https://www.nowcoder.com/practice/769d45d455fe40b385ba32f97e7bcded?tpId=37&&tqId=21296&rp=1&ru=/activity/oj&qru=/ta/huawei/question-ranking
在这里插入图片描述

#include <iostream>
using namespace std;

bool isLeapYear(int year)
{
    return (year % 4 == 0 && year % 100 != 0 || year % 400 == 0);
}
int main()
{
    int board[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
    int y, m, d;
    while(cin >> y >> m >> d)
    {
        int res = 0;
        res += board[m - 1];
        res += d;
        if(isLeapYear(y) && m > 2)
            res += 1;
        cout << res << endl;
    }
    return 0;
}

26.幸运的袋子(回溯+组合)

https://www.nowcoder.com/practice/a5190a7c3ec045ce9273beebdfe029ee?tpId=85&&tqId=29839&rp=1&ru=/activity/oj&qru=/ta/2017test/question-ranking
在这里插入图片描述
题解:组合问题的通用解法:枚举每个节点的组合,只要符合条件结果++,不满足则跳出循环。在枚举下一个节点之前,应该进行剪枝:防止重复节点

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

int LuckPacket(vector<int>& vec, int pos, int sum, int mul)
{
    int count = 0;
    // 每一个位置上的组合都要求一次
    for(int i = pos; i < vec.size(); i++)
    {
        sum += vec[i];
        mul *= vec[i];
        if(sum > mul)
            count += 1 + LuckPacket(vec, i + 1, sum, mul);
        else if(vec[i] == 1)
            count = LuckPacket(vec, i + 1, sum, mul);
        else
            break;
        // 剪枝,防止重复的组合
        while(i < vec.size() - 1 && vec[i] == vec[i + 1])
            i++;
        // 进行下一个组合时,减去当前的值
        // 这里每一次循环相当于把一个值的每种组合都试一次,然后去掉当前节点,去试下一个节点的值的各种组合
        // 例如,1123。先把1的所有组合试一遍:1123,12,13,之后再试2节点
         sum -= vec[i];
         mul /= vec[i];
    }
    return count;
}
int main()
{
    int n;
    cin >> n;
    vector<int> vec(n);
    for(int& i : vec)
        cin >> i;
    sort(vec.begin(), vec.end());
    cout << LuckPacket(vec, 0, 0, 1) << endl;
    return 0;
}

27.二进制中1的个数(位运算)

https://www.nowcoder.com/practice/1b46eb4cf3fa49b9965ac3c2c1caf5ad?tpId=37&&tqId=21285&rp=1&ru=/activity/oj&qru=/ta/huawei/question-ranking
在这里插入图片描述

#include <iostream>
using namespace std;

int CotOne(int n)
{
    int res = 0;
    while (n)
    {
        res++;
        n = n & (n - 1);
    }
    return res;
}

int main()
{
    int n;
    while (cin >> n)
    {
        cout << CotOne(n) << endl;
    }
    return 0;
}

28.手套(数学)

https://www.nowcoder.com/practice/365d5722fff640a0b6684391153e58d8?tpId=49&&tqId=29337&rp=1&ru=/activity/oj&qru=/ta/2016test/question-ranking
题解:模拟一下找手套的过程然后总结方法

class Gloves {
public:
    int findMinimum(int n, vector<int> left, vector<int> right)  
    {
        // write code here
        // 1.当左右手套其中为0时,另一只的一定要拿
        // 2.因此只需要统计每只手套中不为0的手套数量,再减去最小的数
        int l_sum = 0, l_min = INT_MAX;
        int r_sum = 0, r_min = INT_MAX;
        int sum = 0;
        for (int i = 0; i < n; i++)
        {
            if (left[i] * right[i] == 0)
                sum += left[i] + right[i];
            else
            {
                l_sum += left[i];
                r_sum += right[i];
                l_min = min(left[i], l_min);
                r_min = min(right[i], r_min);
            }
        }
        return sum + min(l_sum + 1 - l_min, r_sum + 1 - r_min) + 1;
    }
};

29.完全数计算(做就行了)

https://www.nowcoder.com/practice/7299c12e6abb437c87ad3e712383ff84?tpId=37&&tqId=21279&rp=1&ru=/activity/oj&qru=/ta/huawei/question-ranking

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

bool isPernum(int tar)
{
    int count = 1;
    for (int i = 2; i <= sqrt(tar); i++)
    {
        if (tar % i == 0)
        {
            if (i != sqrt(tar))
                count = count + tar / i + i;
            else
                count += i;
            if (count > tar)
                return false;
        }
    }
    return count == tar;
}
int CotpNum(int n)
{
    int res = 0;
    for (int i = 2; i < n; i++)
    {
        if (isPernum(i))
            res++;
    }
    return res;
}
int main()
{
    int n;
    while (cin >> n)
    {
        cout << CotpNum(n) << endl;
    }
    return 0;
}

30.扑克牌大小(find、count的使用)

https://www.nowcoder.com/practice/0a92c75f5d6b4db28fcfa3e65e5c9b3f?tpId=49&&tqId=29277&rp=1&ru=/activity/oj&qru=/ta/2016test/question-ranking
题解:

  1. 分六种牌型:单牌,对子,三个,炸弹,顺子,王炸,可以看到每种牌型的空格数都不同
  2. 先判断有没有王炸,王炸大于任何牌
  3. 再分空格数是否相等,如果不相等且没有炸弹则返回ERROR
  4. 其次就是掌握string的find方法和算法中的count方法,find找到则返回下标,没找到返回-1
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
    string poke;
    while (getline(cin, poke))
    {
        if (poke.find("joker JOKER") != -1)     // string.find 没有找到返回-1
        {
            cout << "joker JOKER" << endl;
            continue;
        }
        int pos = poke.find('-');
        string poke1 = poke.substr(0, pos);
        string poke2 = poke.substr(pos + 1);
        int space1 = count(poke1.begin(), poke1.end(), ' ');
        int space2 = count(poke2.begin(), poke2.end(), ' ');
        if (space1 != space2)
        {
            if (space1 == 3)
                cout << poke1 << endl;
            else if (space1 == 3)
                cout << poke2 << endl;
            else
                cout << "ERROR" << endl;
        }
        else
        {
            // 比较第一张牌的大小
            string board = "345678910JQKA2jokerJOKER";
            if (board.find(poke1[0]) > board.find(poke2[0]))
                cout << poke1 << endl;
            else
                cout << poke2 << endl;
        }
    }
    
    return 0;
}

31.杨辉三角变形(滚动数组)

https://www.nowcoder.com/practice/8ef655edf42d4e08b44be4d777edbf43?tpId=37&&tqId=21276&rp=1&ru=/activity/oj&qru=/ta/huawei/question-ranking
题解:每一行只和他的上一行有关系,因此只需要通过上一行的数据计算当前行

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

int OddPos(int n)
{
    vector<int> board(2 * n - 1, 0);
    board[0] = 1;
    for (int i = 2; i <= n; i++)
    {
        for (int j = 1; j < 2 * i - 1; j++)
        {
            board[j] = board[j - 1] + board[j];
            if (i == n && board[j] % 2 == 0)
            {
                return j + 1;
            }
        }
    }
    return -1;
}

int main()
{
    int n;
    while (cin >> n)
    {
        cout << OddPos(n) << endl;
    }
    return 0;
}

32.超长正整数相加(大数相加)

题解:

  1. 模拟加法,从双数的最低位开始,每一位先相加,统计进位和取模后的答案,最后反转字符串
  2. 若最后都相加完毕,而进位不为零,则插入1
  3. 方法二:先设置有效元素为max(s1.size, s2.size()) + 1,从后往前赋值,最后判断第一位是不是0,是0则删除
#include <iostream>
#include <string>
using namespace std;
string addSum(string& s1, string& s2)
{
	string res;					// 和
	int i = s1.size() - 1;		// 标识s1的位置
	int j = s2.size() - 1;		// 标识s2的位置
	int car = 0;				// 进位
	while (i >= 0 || j >= 0)
	{
		if (i >= 0)
			car += s1[i] - '0';
		if (j >= 0)
			car += s2[j] - '0';
		res.push_back(car % 10 + '0');
		car /= 10;
		i--;
		j--;
	}
	if (car)
		res += '1';
	reverse(res.begin(), res.end());
	return res;
}
int main()
{
	string s1, s2;
	while (cin >> s1 >> s2)
	{
		cout << addSum(s1, s2) << endl;
	}
	return 0;
}

33.统计每个月兔子的总数(fib的变形)

https://www.nowcoder.com/practice/1221ec77125d4370833fd3ad5ba72395?tpId=37&&tqId=21260&rp=1&ru=/activity/oj&qru=/ta/huawei/question-ranking
题解:设一个月的兔子总数为f(n),则f(n) = f(n - 1) + f(n - 2),f(n)表示上个月兔子总数,f(n - 2)表示上上个月生产的兔子,也就是当前可以进行生产的兔子总数

#include <iostream>

using namespace std;
// f(n) = f(n - 1) + f(n - 2);
int RitCount(int mounth)
{
    if (mounth < 3)
         return 1;
    // dp[0]:代表下个月可生产
    // dp[1]:代表可生产
    int res;
    int dp[2] = { 1, 1 };
    for (int i = 3; i <= mounth; i++)
    {
        res = dp[0] + dp[1];
        dp[0] = dp[1];
        dp[1] = res;
    }
    return res;
}
int main()
{
    int mounth;
    while (cin >> mounth)
    {
        cout << RitCount(mounth) << endl;
    }
    return 0;
}

34.字符串通配符(递归)

https://www.nowcoder.com/practice/43072d50a6eb44d2a6c816a283b02036?tpId=37&&tqId=21294&rp=1&ru=/activity/oj&qru=/ta/huawei/question-ranking
题解:

  1. 当两位置的字符相同或者str1为 ‘?’ 时,则继续往后检测
  2. 当两位置不同并且,str1为 ‘*’ 则分三种情况 1.匹配0个字符 2.匹配1个字符 3.匹配多个字符,只要三种情况有一种为真,则返回真
  3. 如果位置不同,且不为 ‘?’ 和 ‘*’ 则返回false
#include <iostream>
#include <string>
using namespace std;

bool CheckSame(const char* str1, const char* str2)
{
    if (*str1 == '\0' && *str2 == '\0')
        return true;
    if (*str1 == '\0' || *str2 == '\0')
        return false;
    if (*str1 == *str2 || *str1 == '?')
    {
        return CheckSame(str1 + 1, str2 + 1);
    }
    if (*str1 == '*')
    {
        return CheckSame(str1 + 1, str2) || CheckSame(str1 + 1, str2 + 1) || CheckSame(str1, str2 + 1);
    }
    return false;
}
int main()
{
    string str1, str2;
    while (cin >> str1 >> str2)
    {
        if (CheckSame(str1.c_str(), str2.c_str()))
            cout << "true" << endl;
        else
            cout << "false" << endl;
    }
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值