Day 14周二

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);
    }
};
  1. 队列实现栈

在C++中,栈和队列不算是容器,更多的应算上是容器适配器,因为他们底层默认都是双向队列实现的,对一些功能进行限制,封装成为了栈和队列的形式。

在这里用的是双队列的方式来实现的

class MyStack {
public:
    //一个队列用来存放数据,一个队列用来备份数据
    queue que1;
    queue 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 
class Solution {
public:
    bool isValid(string s)
    {
        //关于匹配的问题,都可以判断奇偶性
        if (s.size() % 2 == 1) return false;
        stack 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 
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 
using namespace std;
class Solution {
public:
    void Reverse(string &s)
    {
        for(int i = 0,j = s.size()-1;i 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
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& tokens)
    {
        if (tokens.size() == 0)  return 0;
        stack 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 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& 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 maxSlidingWindow(vector& nums, int k) 
    {
        vector 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一个子类,然后使用基类指针指向该子类对象,释放基类指针时可以释放掉子类的空间,防止内存泄漏。

原型模式

用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象,简单理解就是“克隆指定对象

  1. 提供一个抽象原型类:规定了具体原型对象必须实现的接口。
  2. 提供多个具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
  3. 提供访问类:使用具体原型类中的 clone() 方法来复制新的对象。
//原型模式
#include 
#include 
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;
}

创建模式的总结

工厂模式: 就是单个类的创建工作

抽象工厂模式:多个类的创建工作

单例模式:类的全局对象创建工作

建造者模式:复杂类的对象创建工作

原型模式:自身类的克隆模式

你可能感兴趣的:(每日博客,开发语言,c++)