新的一周,加油~,每天进步一点点~。
算法题(牛客网)
1. 斐波那契数列
斐波那契数列从第三项开始,等于前两项的和。
代码详情:
class Solution {
public:
int Fibonacci(int n) {
vector<int> dp(n + 1);
dp[1] = 1; //初始化一二项
dp[2] = 1;
for(int i = 3; i <= n; i++){
dp[i] = dp[i-1] + dp[i-2]; //等于前两项的和
}
return dp[n];
}
};
2.最长回文子串
自己想不出来,看了答案,动态规划,中心扩展,manacher算法,最后还是选择了中心扩展,动态规划太乱,manacher有点难理解。
代码详情:
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param A string字符串
* @return int整型
*/
int getLongestPalindrome(string A) {
// write code here
for(int i = 0;i < A.size();i += 2){ //统一奇偶字符串
A.insert(i, "#");
}
A.push_back('#');
int max_length = 1; //存储最长回文子串长度
for(int i = 0;i < A.size();++i){
int l = i-1,r = i+1; //创建左右指针
int length = (A[i] == '#')?0:1; //注意是否是'#'
while(l >= 0 && r < A.size()){
if (A[l] == '#'){
l--,r++;
continue; //不计算'#'字符
}
if (A[l--] == A[r++]){
length += 2;
}
else{
break;
}
}
max_length = max(max_length,length);
}
return max_length;
}
};
3. 三数之和
和两数之和还是有点区别的,使用双指针的方法,一个固定,左右指针从两端往里查找。
代码详情:
class Solution {
public:
vector<vector<int> > threeSum(vector<int> &num) {
int n = num.size();
vector<vector<int>> res; //存储最终答案
if (n < 3) return res;//边界判断
sort(num.begin(), num.end()); //重新排号序
for(int i = 0; i < n; ++i){
if (num[i] > 0) break; //大于零后面都大于零了
if (i > 0 && num[i] == num[i-1]) continue;
int l = i + 1,r = n - 1; //创建左右指针
while(l < r){
if (num[i] + num[l] + num[r] > 0){ //如果和大于零说明r大了
--r;
}
else if (num[i] + num[l] + num[r] < 0){ //同理
++l;
}
else{
int m = res.size();
//判断是否和上一个压入数组相等
if(m > 0 && (res[m-1][0] != num[i] || res[m-1][1] != num[l] || res[m-1][2] != num[r])){
res.push_back({num[i],num[l],num[r]});
}
else if (m == 0){
res.push_back({num[i],num[l],num[r]});
}
--r,++l; //可能还存在其他数组相加为零
}
}
}
return res;
}
};
算法题(英雄哥的九日集训-第一天)
1. 两整数之和
不允许用+、-运算符,看来只能用位运算了。看了答案也不是很懂,只能死记硬背了。
代码详情:
class Solution {
public:
int getSum(int a, int b) {
while(b != 0){
unsigned int carry = (unsigned int)(a & b) << 1; //获取无符号进位
a = a ^ b; //相加
b = carry;
}
return a;
}
};
通过详情:
2.不用加号的加法
这么神奇,一样的题目,怎么难度不一样?我又想到了将二进制转换为数组,在数组里面进行操作,类似昨天的字符串相加那样。
代码详情:
class Solution {
public:
int add(int a, int b) {
while(b != 0){
unsigned int carry = (unsigned) (a & b) << 1;
a = a ^ b;
b = carry;
}
return a;
}
};
通过记录:
3.不用加减乘除做加法
怎么一道题,怎么多种问法呢,可能想让我们熟能生巧吧!
代码详情:
class Solution {
public:
int add(int a, int b) {
while(b != 0){
unsigned int carry = unsigned (a & b) << 1;
a ^= b;
b = carry;
}
return a;
}
};
通过详情:
4.递归乘法
终于不是加法了,但是我不会了哈哈哈。看完答案,大概知道好像是,将乘法变成加法来进行运算,但位运算为什么那么位不是很懂,暂时先死记硬背了。
代码详情:
class Solution {
public:
int multiply(int A, int B) {
int ans=0;
for(long long a = max(A,B), b = min(A,B); b; b >>= 1,a += a){
if(b & 1) ans += a;
}
return ans;
}
};
通过详情:
5.两数相除
哈哈哈,看了题解,算了算了,暂时先放下,过于困难。
面试题
1. 多态的实现
首先什么是多态?多态的定义:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。多态有两种类型:编译和运行。
那为什么需要多态呢?为了增强程序的可扩充性,后期修改时,需要改动和增加的代码较少。
那如何实现多态呢(也就是面试问题)?关键在于通过基类指针或引用调用虚函数。每个有虚函数的类都会有个虚函数表,该类的任何对象都有虚函数的指针。
2.赋值符重载与拷贝构造函数的区别
首先什么是赋值符重载?重载operator =函数,当给一个对象赋值时,会调用重载过的赋值运算符。那什么是拷贝构造函数呢?以拷贝的方式初始化一个对象时,会调用拷贝构造函数。
最大区别是赋值运算符没有新的对象生成,而拷贝构造函数会生成新的对象。
3.拷贝构造函数何时调用
1.当用类的一个对象初始化类的另一个对象时
2.函数的形参是类的对象,调用该函数时。
3.函数的返回值是类的对象,函数执行完成返回调用时。
4.四种类型转换运算符
又23点43分了,美好的一天结束了,期待明天清早的太阳,加油~~~