耐心是成功的唯一秘诀
1.lamada表达式是什么?
cpp
auto cmp = [](ListNode * a,ListNode * b){
return a->val > b->val;
}
priority_queue<ListNode*, vector<ListNode*>, decltype(cmp)> heap(cmp);
先来复习一下lamda表达式中的 ( ){ }中分别放的什么意思?
① [] - 捕获列表
指定外部变量如何在 Lambda 内部使用
|-----------|---------------|--------|---------|
| [] | 不捕获任何变量 | - | 只能使用参数 |
| [=] | 值传递捕获所有变量 | ❌ 不能修改 | 拷贝一份,只读 |
| [&] | 引用传递捕获所有变量 | ✅ 可以修改 | 直接引用原变量 |
| [x] | 值传递捕获变量 x | ❌ 不能修改 | 只捕获 x |
| [&x] | 引用传递捕获变量 x | ✅ 可以修改 | 只捕获 x |
| [=, &x] | 值传递捕获所有,x 用引用 | x 可修改 | 混合捕获 |
| [&, x] | 引用传递捕获所有,x 用值 | x 不可修改 | 混合捕获 |
| [this] | 捕获当前对象的 this | ✅ 可以修改 | 在类中使用 |
② ()-参数列表
和普通函数的参数一样
cpp
auto lambda1 = []() { return 10; }; // 无参数
auto lambda2 = [](int a) { return a * 2; }; // 一个参数
auto lambda3 = [](int a, int b) { return a + b; }; // 多个参数
auto lambda4 = [](ListNode* node) { return node->val; }; // 自定义类型
③ { } - 函数体
具体的函数实现,和普通函数没有什么区别
总的来说,lamda表达式其实就是一个简易函数,而前面我们说的cmp就是这个函数的函数名;
2.怎么在算法中创建堆?
cpp
auto cmp = [](ListNode * a,ListNode * b)
{
return a->val > b->val;
}
priority_queue<ListNode*, vector<ListNode*>, decltype(cmp)> heap(cmp);

上面的cmp中的 a->value > b->val,表示这个是小根堆,cmp给heap传给构造参数的意思;默认不写比较器的lamda函数实现的是小根堆;
想要实现大根堆就自定义lamda函数,并且将其中的a->val > b->val 写成 a->val < b->val,为什么a->val > b->val 反而实现的是小根堆呢?
因为 priority_queue 的比较逻辑是:当比较器返回 true 时,第一个参数被认为"优先级更低"。所以 a->val > b->val 让值大的节点"优先级低",值小的节点"优先级高",自然就形成小根堆(值小的在顶部)。

参数1 (Type) = 队列中存什么类型的数据
参数2 (Container) = 用什么容器来存储这些数据
参数3 (Compare) = 用什么规则来比较大小
记忆点:为什么建堆的类型是优先队列,优先队列和堆的关系是什么?这是因为堆本质上是队列的一个变种,由队列的先进先出变种成出去的时候是优先级更高的先出去,所以堆也叫做优先级队列;
3.vector<int> s={0}和vector<int> s的区别是什么?

所以不是所有的变量都要有初始值的;
4.如何判断一个数在不在hash表中(count)
hash.count(x); 如果在的话返回true不在的话返回false;hash.count的时间复杂度是O(1),count的底层逻辑看的是key
5.hashx返回的究竟是什么
如果x是下标的话,呢hashx返回的就是x下标对应的value,如果x是值的话,呢hashx返回的就是下标;
6.unordered_map和unordered_set的区别是什么?

7.中心扩展算法
用于处理回文字符串问题,先固定一个中心点,从中心点开始,向两边扩展,奇数长度以及偶数长度都需要考虑;当是偶数的时候要先让left或者right走一步然后再进行向两边拓展;

class Solution {
public:
string longestPalindrome(string s)
{
//中心拓展算法
int begin =0;
int end = 0;
int n=s.size();
int len =0;
for(int i=0;i<n;i++) //依次枚举每一个中心结点
{
int left =i;
int right =i;
//进行奇数次的中心拓展
while(left>=0 && right< n && s[left] == s[right])
{
left--;
right++;
}
//更新最长回文子串的长度
if(right-left-1 > len)
{
begin = left+1;
len = right-left-1;
}
//进行偶数次的中心拓展
left = i;
right = i+1;
while(left>=0 && right< n && s[left] == s[right])
{
left--;
right++;
}
//更新最长回文子串的长度
if(right-left-1 > len)
{
begin = left+1;
len = right-left-1;
}
}
return s.substr(begin,len);
}
};
8.什么是高精度加减乘除?
所谓的高精度就是位数多到我们的double都没办法存储,对于它的加减乘除计算我们要使用模拟的方法;
而它的背后是对我们小学学习的列竖式的模拟;
9.在算法题中怎么进行数字和字符的转换

10.字符串相乘
我们这里说的字符串其实就是高精度数字,对于这样的数字想要进行乘法,接着使用传统的模拟乘法运算的列竖式是不够的,细节太多很容易出错,所以我们应该使用的是无进位相乘再相加的方法,这种方法的好处在于处理的细节会变少;

cpp
class Solution {
public:
string multiply(string num1, string num2)
{
reverse(num1.begin(),num1.end());
reverse(num2.begin(),num2.end());
int m=num1.size();
int n=num2.size();
vector<int> result(m+n-1);
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
result[j+i] += (num2[i]-'0')*(num1[j]-'0');
}
}
string ret;
int t=0;
int cur =0;
while(cur< m+n-1 || t!=0)
{
if(cur<result.size()) t +=result[cur++];
ret += t%10+'0';
t/=10;
}
//处理前导0
while(ret.size()>1 && ret.back() =='0') //result.size()>1这是为了防止当只有一个0的时候还被删除掉
{
ret.pop_back();
}
reverse(ret.begin(),ret.end());
return ret;
}
};
