取数组中任意个数相加,但是取的数不能相邻,输出最后得到的和的最大值

前言

2020-3-25 唯品会笔试编程题

前言

翻转链表

通过SQL计算每天的总销量和平均销量

数组最大值

翻转链表

题目

剑指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();
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值