Day 14周二
每日算法
题目1
反转字符串
妈的这个代码我刚刚开始看了半天,想着,里面的那个reverse为什么就不反转啊,结果是我sb了,那个for循环的括号没有把start = i + 1;给包含进去,找个start根本一直都是在i的后面,我真的服了我去
class Solution {
public:string reverseWords(string &s) {RemoveSpace(s);Reverse(s, 0, s.size()-1);int start = 0;for (int i = 0; i <= s.size(); ++i){if (i == s.size() || s[i] == ' ') //Reverse(s, start, i - 1);//start = i + 1; //start指向了下一个元素的开头//所以这里有应该是加上一个{}{Reverse(s, start, i - 1);start = i + 1;}}return s;}private:void Reverse(string &s, int left, int right){for (int i = left, j = right; i < j; i++, j--){swap(s[i], s[j]);}}void RemoveSpace(string& s){ int slowIndex = 0;for (int fastIndex=0; fastIndex < s.size(); fastIndex++){if (s[fastIndex] != ' '){if (slowIndex != 0) s[slowIndex++] = ' ';while (fastIndex < s.size() && s[fastIndex] != ' '){s[slowIndex++] = s[fastIndex++];}}}s.resize(slowIndex);}
};
- 队列实现栈
在C++中,栈和队列不算是容器,更多的应算上是容器适配器,因为他们底层默认都是双向队列实现的,对一些功能进行限制,封装成为了栈和队列的形式。
在这里用的是双队列的方式来实现的
class MyStack {
public://一个队列用来存放数据,一个队列用来备份数据queue<int> que1;queue<int> que2;MyStack() {}void push(int x) {que1.push(x);}int pop() {int size = que1.size();size--;while(size--){//把que1中的所有元素都弹到que2中,然后只留下一个元素即可int res1 = que1.front();que2.push(res1);que1.pop();}int res = que1.front();que1.pop();que1 = que2;while(!que2.empty()){que2.pop();}return res;}int top() {return que1.back();}bool empty() {return que1.empty() && que2.empty();}
};/*** Your MyStack object will be instantiated and called as such:* MyStack* obj = new MyStack();* obj->push(x);* int param_2 = obj->pop();* int param_3 = obj->top();* bool param_4 = obj->empty();*/
括号的匹配
#include <stack>
class Solution {
public:bool isValid(string s){//关于匹配的问题,都可以判断奇偶性if (s.size() % 2 == 1) return false;stack<char> sta;for (size_t i = 0; i < s.size(); i++){//判断是否是左括号if (s[i] == '(') sta.push(')');else if (s[i] == '{') sta.push('}');else if (s[i] == '[') sta.push(']');//如果不是左括号,是右括号的情况下//1. 如果我们的栈为空了,但是现在我们还是有右括号,说明右括号多了//2. 如果我们当前的右括号和栈中的不匹配,说明是左括号多了else if (sta.empty() || sta.top() != s[i]) return false;//3. 这个时候说明是相等的else sta.pop();}//此时我们遍历完了这个字符串,如果队列为空,说明我们的括号是刚好匹配的//如果我们的栈中还是有元素的,就说明左括号是多的return sta.empty();}
};
设计模式
最好这两天就可以吧设计模式的内容全部都第一次初步的过一遍
工厂设计模式
1.提供一个抽象工厂类 :所有具体工厂类的父类
2.提供与产品对应的工厂类:负责实例化产品对象
3.提供一个抽象产品类: 所有产品的父类
4.提供一个或多个产品类:工厂方法模式所创建的具体实例对象
#include <iostream>
using namespace std;
class AbstractProduct
{
public:virtual void makeProduct() = 0;
};class AbstractFactory
{
public:virtual AbstractProduct* createProduct() = 0;
};class PlaneProduct :public AbstractProduct
{
public:void makeProduct(){cout << "造飞机....." << endl;}
};class PlaneFactory :public AbstractFactory
{
public:AbstractProduct* createProduct(){AbstractProduct* product = new PlaneProduct;return product;}
};class RocketProduct :public AbstractProduct
{
public:void makeProduct(){cout << "造火箭...." << endl;}
};class RocketFactory :public AbstractFactory
{
public:AbstractProduct* createProduct(){AbstractProduct* product = new RocketProduct;return product;}
};int main()
{//造飞机AbstractFactory* factory = new PlaneFactory;AbstractProduct* product = factory->createProduct();product->makeProduct();//造火箭factory = new RocketFactory;product = factory->createProduct();product->makeProduct();return 0;
}
抽象工厂模式
//工厂模式
//抽象产品,总的
class Product
{
public:virtual void show() = 0;
};//抽象产品族 1,表示为键盘
class KeyBoard : public Product{};//具体产品 1
class LogicalKeyBoard : public KeyBoard
{
public:void show(){std::cout << "这是逻辑键盘" << char(10);}
};class LeiSheKeyBoard : public KeyBoard
{
public:void show(){std::cout << "这雷蛇键盘" << char(10);}
};//抽象产品族2
class Mouse :public Product{};//具体产品2
class LogicalMouse :public Mouse
{
public:void show(){std::cout << "这是逻辑的鼠标" << char(10);}
};class LeiShelMouse :public Mouse
{
public:void show(){std::cout << "这是雷蛇的鼠标" << char(10);}
};//抽象工厂
//在这个抽象工厂中定义两个纯虚函数,这两个函数是用来创建产品的
class AbstractFactory
{
public:virtual KeyBoard* createKeyBoard() = 0;virtual Mouse* createKeyMouse() = 0;
};//具体工厂
//逻辑工厂
class LogicalFactory:public AbstractFactory
{
public:KeyBoard* createKeyBoard(){std::cout << "逻辑工厂制造了产品:逻辑键盘" << char(10);return new LogicalKeyBoard;}Mouse* createKeyMouse(){std::cout << "逻辑制造了产品:逻辑鼠标" << char(10);return new LogicalMouse;}
};class LeiSheFactory : public AbstractFactory
{
public:KeyBoard* createKeyBoard(){std::cout << "雷蛇工厂制造了产品:雷蛇键盘" << char(10);return new LeiSheKeyBoard;}Mouse* createKeyMouse(){std::cout << "雷蛇工厂制造了产品:雷蛇鼠标" << char(10);return new LeiShelMouse;}
};int main()
{//通过抽象工厂的指针来指向一个具体的工厂,来调用具体工厂里面的方法AbstractFactory* factory = new LogicalFactory;KeyBoard* key = factory->createKeyBoard();Mouse* mouse = factory->createKeyMouse();key->show();mouse->show();delete factory;delete key;delete mouse;//再一次创建的时候,需要把new出来的指针进行置空的处理factory = new LeiSheFactory;key = factory->createKeyBoard();mouse = factory->createKeyMouse();key->show();mouse->show();delete factory;delete key;delete mouse;factory = nullptr;key = nullptr;mouse = nullptr;return 0;
}
Day 15 周三
每日算法
删除字符串中的重复字符
#include <stack>
using namespace std;
class Solution {
public:void Reverse(string &s){for(int i = 0,j = s.size()-1;i<j;i++,j--){swap(s[i],s[j]);}}string removeDuplicates(string s){stack<char> sta{};string result{};for (int i = 0; i < s.size(); i++){if (sta.empty() || sta.top()!=s[i]){sta.push(s[i]);}else{sta.pop();}}//再这里把栈中的元素传入while (!sta.empty()){result += sta.top();sta.pop();}Reverse(result);return result;}
};
逆波兰求表达式
自己第一次写的时候出现了发现结果总是对不上,检查了逻辑是发现没有任何的问题的
打了断点去看函数里面的返回结果,发现result里面的返回结果是0,是传入的num的数值是错误的
#include<stack>
using namespace std;
class Solution {
public://如果一个计算机逻辑是没有问题的话,我们可以考虑一下是否是数值的传入顺序的问题long long Culute(string &fuhao,long long &num1,long long &num2){int result = 0;if (fuhao == "+") result = (num1 + num2);else if (fuhao == "-") result = (num1 - num2);else if (fuhao == "*") result = (num1 * num2);else result = (num1 / num2);return result;}int evalRPN(vector<string>& tokens){if (tokens.size() == 0) return 0;stack<long long> sta;for (int i = 0; i < tokens.size(); i++){if (tokens[i] == "+" || tokens[i] == "-"|| tokens[i] == "*" || tokens[i] == "/"){long long num1 = sta.top();sta.pop();long long num2 = sta.top();sta.pop();long long push_value = Culute(tokens[i],num1,num2);sta.push(push_value);//sta.push( Culute(tokens[i],num1,num2) );}else{//把数字存放到栈当中去sta.push(stoll(tokens[i]));}}long long result = sta.top();sta.pop();return result;}
};int main()
{Solution s;vector<string> tokens;tokens.push_back("4");tokens.push_back("13");tokens.push_back("5");tokens.push_back("/");tokens.push_back("+");s.evalRPN(tokens);return 0;
}
239滑动窗口的最大值
代码的逻辑应该是没有什么问题的,只是Leetcode里面超时了
class Solution {
public:int FindMax(vector<int>& nums,int start,int end){int max = INT_MIN;for (int i = start; i <= end && i < nums.size(); i++){if (nums[i] > max){max = nums[i];}}std::cout << max << char(10);return max;}vector<int> maxSlidingWindow(vector<int>& nums, int k) {vector<int> result;for (int left = 0, right = k - 1; right <= nums.size()-1; left++, right++){int max = FindMax(nums, left, right);result.push_back(max);}return result;}
};
为什么析构函数要是虚函数
- 将可能会被继承的父类的析构函数设置为虚函数,可以保证当我们new一个子类,然后使用基类指针指向该子类对象,释放基类指针时可以释放掉子类的空间,防止内存泄漏。
原型模式
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象,简单理解就是“克隆指定对象”
- 提供一个抽象原型类:规定了具体原型对象必须实现的接口。
- 提供多个具体原型类:实现抽象原型类的
clone()
方法,它是可被复制的对象。 - 提供访问类:使用具体原型类中的
clone()
方法来复制新的对象。
//原型模式
#include <iostream>
#include <string>
using namespace std;//提供一个抽象的类
class Monkey
{
public:Monkey() = default;virtual ~Monkey() = default;virtual Monkey* Clone() = 0;virtual void Play() = 0;
};//定义的一个具体的类
class SunWuKong:public Monkey
{
public:~SunWuKong() {};SunWuKong(string m_name){name = m_name;}//拷贝构造函数SunWuKong(const SunWuKong &other){//因为这里不涉及到深拷贝的内容,所以就是简单的浅拷贝赋值操作name = other.name;}Monkey* Clone() {//调用拷贝构造函数return new SunWuKong(*this);}void Play(){std:cout << name << "调用成功了哦" << char(10);}
private:string name;
};int main()
{//父类的指针指向子类Monkey* monkey = new SunWuKong("美猴王齐天大圣");//相当于我创建的这两个克隆都是齐天大圣Monkey* Kelong1 = monkey->Clone();Monkey* Kelong2 = monkey->Clone();Kelong1->Play();Kelong2->Play();Monkey* Kelong3 = Kelong1->Clone();Kelong3->Play();return 0;
}
创建模式的总结
工厂模式: 就是单个类的创建工作
抽象工厂模式:多个类的创建工作
单例模式:类的全局对象创建工作
建造者模式:复杂类的对象创建工作
原型模式:自身类的克隆模式