【c++5道练习题】②

【c++5道练习题】②_第1张图片

目录

 一、验证回文串

二、字符串相加

三、杨辉三角

四、最小栈

五、栈的压入、弹出序列 


 一、验证回文串

【c++5道练习题】②_第2张图片

 思路:

1、注:for(auto ch : s)  -》指将s中每一个字符赋值给ch,ch的改变并不会影响s

但写为for(auto& ch : s) -》指将ch是s中每一个字符的引用,ch的改变影响s

2、将字符串中大写都转为小写或小写都转为大写,那判断是否为字母时,只需判断是否为小写字母即可,但这点最好的点在于比较字母时可以直接比较,因为都是统一的字母。

3、在走的过程中begin是因为如果一直没遇到字母和数字字符,不能让他一直走,走到尾要结束

代码如下: 

class Solution {
public:
	//判断是否为字母或数字
	bool isCharOrNumber(char ch)
	{
		if ((ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9'))
			return true;
		else
			return false;
	}
	//验证回文串
	bool isPalindrome(string s) {
		//1、将字符串中所有的大写字母转成小写
		for (auto& ch : s)
		{//取别名才能改变ch
			if (ch >= 'A' && ch <= 'Z')
			{
				ch += 32;
			}
		}
		//2、用快排的思路进行比较
		int begin = 0, end = s.size() - 1;
		while (begin < end)
		{//比较的大前提是begin < end

			while (begin < end && !isCharOrNumber(s[begin]))
				++begin;//若不是字母或数字则begin++往后找
			while (begin < end && !isCharOrNumber(s[end]))
				--end;//若不是字字母或数字则end--往前找

			//找到字母或数字了则开始比较
			if (s[begin] != s[end])
			{
				return false;
			}
			else
			{
				++begin;
				--end;
			}
		}
		return true;
	}
	
};

二、字符串相加

【c++5道练习题】②_第3张图片

题目的意思是字符串变为整数相加后又变为字符串的形式 ,那这个字符串是多少?不允许字符串直接全转换为整形后相加,因为如果这个字符串很长,转换是存不下的

先给代码后说思路:

class Solution {
public:
	string addString(string num1, string num2) {
		//end1和end2从两个字符串的最后一位开始往前比
		int end1 = num1.size() - 1, end2 = num2.size() - 1;
		int next = 0;//用来保存是否进一位
		string retstr;//此字符串用来保存结果并返回
		while (end1 >= 0 || end2 >= 0)
		{//两个字符串都结束了才算结束
			int val1 = 0, val2 = 0;
			if (end1 >= 0)//>=0说明没走完,因为存在一个字符串走完另个字符串没走完的情况
				val1 = num1[end1] - '0';//将字符转换为数字

			if (end2 >= 0)
				val2 = num2[end2] - '0';

			int ret = val1 + val2 + next;//转换成的数字相加
			if (ret > 9)
			{
				ret -= 10;//>9则需要进位
				next = 1;//进位出来的1
			}
			else
			{//加出来的那一位ret<=9则无需进位,next=0
				next = 0;
			}

			//retstr.insert(retstr.begin(), '0' + ret);
			ret += (ret + '0');//再把这一位转换为字符尾插到ret末尾
			--end1;//--来进行前一位的相加
			--end2;
		}
		if (next == 1)
		{//在最后一次若next==1,尾插一个'1'
			//retstr.insert(retstr.begin(), '1');
			retstr += '1';
		}
		
		//因为之前是尾插的,那正确的字符串应该逆置
		reverse(retstr.begin(), retstr.end());

		return retstr;
	}
};

思路:

对于两个字符串从后往前一位一位进行相加,当然,字符不能直接相加,我们先把每一位对应的字符先转换为数字相加,如果加出来的这一位>9,则next=1(next用来表示是否进位) ,若<9,则next=0,当前一位的对应字符相加时就要加上next,进不进位就由next来区分

代码中的剖析:

 ①、while结束条件是end1 >= 0 || end2 >= 0  因为给的字符串可能一个长一个短,只有长的也结束了相加才结束,所以用或,end1和end2原来给的是字符串最后一个字符的下标,若end1<0说明end1对应的字符串走完了,end2同理

②、走的过程中要判断end1和end2是否>=0,因为存在一个字符串长一个字符串短的情况,长的没走完还要进入循环中,短的字符串走完了就不用计算了,所以如果>=0说明还没走完,要继续计算

③、字符的插入方式:

1、用insert来头插,但头插需要每次都向后移动,现有几个元素就需移几次,每次都头插一个元素,有一个元素需移动一次,两个元素需要移动两次,n个元素需要移动n次,1+2+...+n,故时间复杂度:O(N*N),效率不好

2、每插入一个元素都尾插,最后全尾插完再用algorithm中的reverse实现(需#include),时间复杂度:O(N),故推荐此方式

下面给出一个例子:

【c++5道练习题】②_第4张图片

三、杨辉三角

题述:

 给定一个非负整数 numRows,生成杨辉三角的前 numRows行。

【c++5道练习题】②_第5张图片

示例:

【c++5道练习题】②_第6张图片

题中已给:

class Solution {
public:
	vector> generate(int numRows) {

	}
};

 知识点:理解vector>vv

【c++5道练习题】②_第7张图片

思路: 

对于杨辉三角的实际状态,除了1外,每个数=上一行同下标的数+上一行同下标-1的数,而每一行的首元素和尾元素都会是1,利用这个规律就好求解了 

代码如下:

class Solution {
public:
	vector> generate(int numRows) {
		vector> vv;
		vv.resize(numRows);//开辟numRows个(行)
		for (size_t i = 0; i < numRows; ++i)
		{
			vv[i].resize(i + 1);//每一行对应开i+1个
			vv[i][0] = 1;//每一行的第一个元素为1
			vv[i][vv[i].size() - 1] = 1;//每一行的最后一个元素为1
		}

		for (size_t i = 0; i < vv.size(); ++i)
		{
			for (size_t j = 0; j < vv[i].size(); ++j)
			{
				if (vv[i][j] != 1)
				{//不是首尾元素的,则等于上一行同列下标+同列下标-1的值
					vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];
				}
			}
		}

		return vv;
	}
};

四、最小栈

题述:

设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。

  • push(x)—— 将元素 x 推入栈中。
  • pop()—— 删除栈顶的元素。
  • top()—— 获取栈顶元素。
  • getMin()—— 检索栈中最小元素

输入:["MinStack","push","push","push","getMin","pop","top","get"]

[[ ],[-2],[0],[-3],[ ],[ ],[ ],[ ]]

输出:

[null,null,null,null,-3,null,0,-2]

题中已给:

class MinStack {
public:
	/* initialize your data with structure here */
	MinStack() {

	}
	
	void push(int x) {

	}

	void pop() {

	}

	int top() {

	}

	int getMin() {

	}
};

思路:

①、错误思路:

用两个栈,假设为栈A栈BA用来把所有元素一个个入栈B用来存最小元素

假如A中要存数据5 2 1 6,那么初始先入5到B,再考虑2,2比5小,删除B的栈顶,再把2入B,再考虑1,1比2小,删除B的栈顶,再把1入B,再考虑6,6没2小,不入B,那么B中最小的就是栈顶

但是若删除A中数据呢,B也受影响?栈一定是从栈顶开始删的,删除完后再找最小的元素就找不到了,因为之前的都被删除了。但是可以再遍历一遍A,再找最小元素,但这不符合题目规定的常数时间了,故这种方法不可以

②、正确思路:

用两个栈,假设为栈A栈B,跟错误思路的区别就是,B中不是只存最小的元素,而是在每次比较中,只要比B当前的栈顶元素小或等于的都入B,不删除之前的元素,那么再删除栈顶的时候,只有当B中和A中的元素相同时,才会删除B的栈顶,删除完后的栈顶还是当前最小的元素

 代码如下:

//最小元素
class MinStack {
public:
	/* initialize your data with structure here */
	MinStack() {}//因为栈是自定义类型,他有自己的构造函数,故构造函数可不写
	
	void push(int x) {
		_st.push(x);//_st的所有数据都会入栈
		if (_minst.empty() || _minst.top() >= x)
		{//只有当没数据或栈顶的元素>=要入的数据时,才会入_minst

		//重复的最小元素也要入_minst,因为假设有0 1 0三个数先后入_st,那如果
		// 不重复入minst,_minst只有0,当删除0时,_minst为空,再访问最小元素就
		// 没有了,但理应还返回0,所以重复的元素也要入栈
			_minst.push(x);
		}
	}
	
	void pop() {
		if (_st.top() == _minst.top())
			_minst.pop();

		_st.pop();
	}

	int top() {
		return _st.top();
	}

	int getMin() {
		return _minst.top();
	}

	stack _st;//所有数据都入栈
	stack _minst;//每次的更小值入栈
};

五、栈的压入、弹出序列 

题述:

【c++5道练习题】②_第8张图片

题意是入栈的顺序是固定的,但出栈有好几种顺序,因为可以边进边出,pushV储存的入栈的元素,popV指的是出栈的元素

思路:

在已知出栈顺序的前提下,定义一个栈st,开始先入一个数据到st中,入完一个数据立即比较,比较跟出栈顺序的第一个元素是否相等,相等则出栈,然后比较下一元素,不相等则再入数据到栈中

注意①:出栈是个while循环操作,条件是栈不为空st中的栈顶=此时popV指向的当前元素才行,栈不为空才出栈因为可能在连续出栈的过程中栈为空了,这时应该再入数据

注意②:入栈直到栈数据全入完了才终止,那么入完了就可以判断顺序是否合法,此时只要栈中还有数据就是不合法没数据才合法,因为只有出栈入栈的顺序合法才会为空

【c++5道练习题】②_第9张图片 代码实现:

class Solution {
public:
	bool IsPopOrder(vectorpushV, vectorpopV) {
		//栈来模拟进出 (用vector类似于用了c语言中的数组)
		stack st;
		int pushi = 0, popi = 0;//入栈和出栈的下标
		while (pushi < pushV.size())//当走到尾就可判定了,但在这之前都要入栈
		{
			st.push(pushV[pushi]);//入数据
			++pushi;
			//入完一个数据就要立即跟已给的出栈顺序比较
			//因为可能要连续出,所以用while循环
			while (!st.empty() && st.top() == popV[popi])
			{
			//1、出到空就不能再出了,要退出while
			//2、若栈顶和已给的出栈顺序的对应位置相同,则进入while
				st.pop();
				++popi;
			}
		}

		//只有入栈的数据全部进入,且最后栈为空就是合法的顺序
		return st.empty();//若为空,则为合法的顺序
	}
};

你可能感兴趣的:(【c++】代码题,c++,算法,开发语言)