前言
2020-3-25 唯品会笔试编程题
翻转链表
题目
剑指offer的原题:https://www.nowcoder.com/practice/75e878df47f24fdc9dc3e400ec6058ca
分析
很容易想到利用 头插法 实现反序。但是指针操作,如果没有想清楚或者忽略一些边界条件就很容易出错。下面是这题的注意事项,代码中也给出了注释。
1. 新建一个辅助的伪头头节点。这是惯用技巧了,规避一些头尾的边界条件。但是之后最好不要忘了回收这个伪头节点的内存,要成好习惯
2. while 循环里面中的 tmp 暂存了当前指针p的下一个节点。因为在执行“头插”操作的时候修改了p->next,所以要提前暂存
3. 新的头节点是first->next。最后,不要忘了回收这个伪头节点的内存
代码
ListNode* ReverseList(ListNode* pHead) {
// 新建一个辅助的伪头节点
ListNode* first = new ListNode(0);
// 利用头插法实现反序
ListNode* p = pHead;
while (p != NULL) {
ListNode* tmp = p->next;
// 头插
p->next = first->next;
first->next = p;
p = tmp;
}
// 新的头节点
pHead = first->next;
// 不要忘了回收伪头节点的内存,要养成好习惯
delete first;
return pHead;
}
通过SQL计算每天的总销量和平均销量
题目
代码
select create_date, count(order_sn), avg(amount)
from vip_sales
group by create_date;
数组最大值
题目
提供一个数组,取数组中任意个数相加,但是取的数不能相邻,输出最后得到的和的最大值,输入的数组的值均为正整数。
样例
输入:[ 2, 3, 2 ]
输出:4
说明:取第1个值和第三个值,2+2 = 4
分析
动态规划。假设num[]表示上述数组,dp[i] 表示数组区间 [0, i] 符合题意的最大值,那么 dp[i] 可以通过递推得出
1. 假设第 i-1 个数要取,则第 i 个数必然不能取(不能取相邻的数),那么此时 dp[i] = dp[i-1]
2. 假设第 i-1 个数不取,则根据贪心的思想,那么第 i 个数一定取(因为每个数都是正整数,能取则取,才可能使结果最大)。那么此时,dp[i] = dp[i-2] + num[i] 。
所以可以得出递推式:dp[i] = max{ dp[i-1], dp[i-2] + num[i] },i>=2。答案即为:dp[ n-1 ],n为数组元素个数
由于 i>=2,所以要想递推,我们需要得到初始的 dp[0],dp[1]。显然吗,dp[0] = num[0],dp[1] = max{ num[0], num[1] }。
代码
int maxValue(vector<int>& num) {
vector<int> dp;
dp.assign(num.size(), 0);
dp[0] = num[0];
dp[1] = max(num[0], num[1]);
if (num.size() == 1) {
return dp[0];
}
if (num.size() == 2) {
return dp[1];
}
for (int i=2; i<dp.size(); i++) {
dp[i] = max(dp[i-1], dp[i-2]+num[i]);
}
return dp.back();
}