算法题
最长递增子序列
给定一个序列,返回最长递增子序列,这里是序列不是子数组。
方法1:DP.dp[i]表示以第i个数作为结尾,递增序列个数,res数组保存当前情况下最长序列。
dp[i] = max(dp[j]+1).
其中,j为小于i的并且nums[j]<nums[j]
vector<int> max_seq(vector<int> &nums) {
vector<int> res;
int n = nums.size();
int max_len = 1;
vector<int> dp(n,1);
res.push_back(nums[0]);
for (int i = 1; i < n; i++) {
for (int j = i - 1; j >= 0; j--) {
if (nums[j] < nums[i] && dp[j] >= dp[i]) {
dp[i] = dp[j] + 1;
}
}
if (dp[i] > max_len) {
max_len = dp[i];
res.push_back(nums[i]);
}
if (dp[i] == max_len) {
res.pop_back();
res.push_back(nums[i]);
}
}
return res;
}
《大话设计模式》
装饰模式
什么时候用? 动态的给一个对象添加功能。
例: 比如person类,给它穿衣服,创建一个Decorator类继承person,作为接口,然后派生类为各种具体装饰类,比如Tshirt,Tie类。
就是说已经写完一个类了,但是后来发现会有新需求,需要更多的功能,那么体现开闭原则。把类的装饰功能从类中去除,这样就可以把类的核心职责和装饰功能区分开。
代理模式
代理模式就是多了一个代理类,真实对象类和代理类继承于同一个类或接口,代理类中包含真实类对象,函数包括真实类中的函数,而且可以增加新的功能,所以体现了开闭原则,创建对象的时候创建代理类就可以,调用函数其实真正起作用的是真实类。
比如前期开发中我们没有加入缓存、日志等这些功能,后期若想加入,我们就可以使用代理来实现,而且不必对原有代码进行改动。
工厂模式
就是对每个产品类,都有一个工厂类生成产品对象,这样,就不需要使用产品类来实例化对象啦。
和简单工厂相比,简单工厂是一个工厂类根据输入参数不同创建不同产品对象,工厂方法模式是每一个产品都有一个工厂类。克服了简单工厂模式违背开放原则的缺点。
原型模式
如果你从一个对象A的实例得到一个和A相同的实例B,而且两个对象互不干扰,就要用原型模式。
原型模式和拷贝构造函数区别:拷贝构造函数具体给出了实现函数,而且只能是同一个类的对象拷贝给相同类的对象,但是原型模式是给出了一个概念或者思路,它不管具体如何实现,而且可以是派生类拷贝基类。
为什么不用new直接创建新对象,再把存在的对象赋值给新对象,而用原型模式?
因为想利用已存在的对象的状态,而且new的效率低。构造函数可能很多个参数,太复杂。
每个派生类都要实现clone函数。
模板方法模式
模板方法模式就是把相同的,不变的操作放到基类中,不同的操作放到派生类中。
体现了代码复用。
缺点:每一个单一功能都要有一个新的类,但是这样,体现了单一功能原则,内聚性更高。