笔试算法题(06):最大连续子数组和 & 二叉树路径和值

出题:预先输入一个整型数组,数组中有正数也有负数;数组中连续一个或者多个整数组成一个子数组,每个子数组有一个和;求所有子数组中和的最大值,要求时间复杂度O(n);

分析:

  • 时间复杂度为线性表明只允许一遍扫描,当然如果最终的最大值为0表明所有元素都是负数,可以用线性时间O(N)查找最大的元素。具体算法策略请见代码和注释;

  • 子数组的起始元素肯定是非负数,如果添加的元素为正数则记录最大和值并且继续添加;如果添加的元素为负数,则判断新的和是否大于0,如果小于0则以下一个元素作为起始元素重新开始,如果大于0并且比最大和值小则不更新最大和值,并且继续添加元素;

  • 当然还有分治的解法,将数组分成A和B两个部分,则子数组最大和有三种可能,来自A,来自B和来自A和B的跨界处,时间复杂度为O(NlogN);

  • 如果数组为循环数组,则说明子数组最大和允许出现在array[n-1]和array[0]作为一部分的组合。这样题目分解为两个子题目,一个子题目就是
    目标值没有跨过array[n-1]和array[0],其实也就是原来的题目;另一个子题目就是目标值为array[i]到array[n-1]和
    array[0]到array[j]的组合,时间复杂度仍旧为O(N);

解题:


 1 /**
2 * 子数组累加和必定是从非负数的元素开始
3 * 如果子数组和小于0则缺省最大值为0
4 * */
5 int MaxSubArray(int *array, int count) {
6 int max=0;
7 int curMax=0;
8 for(int i=0;i<count;i++) {
9 curMax+=array[i];
10 /**
11 * 跳过负数元素,所以目标子数组必定以非负数元素开始
12 * */
13 if(curMax < 0) {
14 curMax=0;
15 continue;
16 }
17 /**
18 * 一旦遇到负数元素,除当前负数元素的其他元素的和作为
19 * 最大值;由于不能保证之后的元素不会让子数组和变得更大
20 * ,所以累加继续
21 * */
22 if(array[i]<0) {
23 if(max<(curMax-array[i])) {
24 max=curMax-array[i];
25 }
26 } else {
27 if(max<curMax) {
28 max=curMax;
29 }
30 }
31 }
32 return max;
33 }
34
35 int MaxDif(int *array, int length) {
36 /**
37 * 定义局部stack数组存储相邻元素差值
38 * 循环获取相邻元素差值
39 * */
40 int difarray[length-1];
41 for(int i=0;i<length-1;i++) {
42 difarray[i]=array[i]-array[i+1];
43 printf("\n%d",difarray[i]);
44 }
45 /**
46 * sum记录最大和值
47 * tempsum记录当前元素的和值
48 * 如果元素为+++++++,则从开始相加到最后
49 * 如果元素为-------,则sum保持为0
50 * 如果元素为++++---,则sum保持为前半正数
51 * 如果元素为----+++,则sum保持为后半正数
52 * 还有其他满足条件的情况
53 * */
54 int tempsum=0, sum=0;
55 for(int i=0;i<length-1;i++) {
56 tempsum+=difarray[i];
57 if(tempsum<0)
58 tempsum=0;
59 else if(tempsum>sum)
60 sum=tempsum;
61 }
62 return sum;
63 }
64
65
66 int main() {
67 int array[]={1,-2,3,10,-4,-7,-2};
68 printf("the max sub array sum: %d",MaxSubArray(array,7));
69 return 1;
70 }

出题:输入一个整数和一颗二元树(节点值为整数),从树的根节点开始往下访问每一个节点,直到叶子节点最终形成一条路径。打印出所有节点和与整数值相等路径;

分析:深度优先搜索,使用Stack结构记录路径;

解题:


 1 /**
2 * 使用path记录路径
3 * */
4 void SpecialDfs(Node *current, MyStack *path, int sum, int target) {
5 path->push(current->value);
6 sum+=current->value;
7 bool isLeaf=true;
8
9 if(current->left != NULL) {
10 SpecialDfs(current->left, path, sum, target);
11 isLeaf=false;
12 }
13
14 if(current->right != NULL) {
15 SpecialDfs(current->right, path, sum, target);
16 isLeaf=false;
17 }
18
19 if(isLeaf && sum == target) {
20 path->showStack();
21 }
22 path->pop(NULL);
23 }

笔试算法题(06):最大连续子数组和 & 二叉树路径和值,布布扣,bubuko.com

时间: 2024-10-26 02:02:24

笔试算法题(06):最大连续子数组和 & 二叉树路径和值的相关文章

最大连续子数组和算法(动态规划解释)

之前在其他博客看到了,但是算法的关键部分完全看不懂为什么要这么做,直到最近上算法课,才终于知道到底怎么来的. 问题描述: 给出一个数组,求其最大连续子数组和 例:数组{1,2,3,4,-5,10,-1,-1}的最大连续子数组和是子数组{1,2,3,4,-5,10}的和15 算法过程: 这个算法能从零直接想出来的人是真的厉害,我并不可以,所以我直接描述一下这个算法是怎么算的,而不描述怎么想到的了 首先我们把原来数组记做a,然后最关键的一步,我们需要一个等长的数组b,b[j]的含义是以下一系列和中的

[算法导论]4.1-5最大连续子数组问题

在线性时间内非递归的求数组的最大连续子数组(连续和最大的子数组). 题目给出思路为数组A[1...j+1]的最大和子数组,有两种情况:a) A[1...j]的最大和子数组; b) 某个A[i...j+1]的最大和子数组,但思考很久没有理解如何用这个思路设计线性时间算法,希望有人能给予指点. (i点是使A[1]+..+A[i]为负的一个值?) 目前的思路是,最大子数组一定位于从某个正数开始,全部求和<=0的一段数组中 从其实点i到目标点j,从第一个正数开始截取尽量长的一段数组,从第一个正数起的最大

编程算法 - 连续子数组的最大和 代码(C)

连续子数组的最大和 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 输入一个整型数组, 数组里有正数也有负数. 数组中一个或连续的多个整数组成一个子数组.求所有子数组的和的最大值. 使用一个数保存当前和, 如果当前和为小于0,  则替换新值, 否则, 递加, 使用一个数保存临时最大值. 代码: /* * main.cpp * * Created on: 2014年6月29日 * Author: wang */ #include <stdio

最大连续子数组算法学习

作为零基础学习的弱智艰难的入行后,在黑暗中摸爬滚打中过了几个月,才想起应该开个博客记录下自己的学习历程和整理知识点.刚刚接触算法的我,博客就以记录我的算法学习历程为开端吧.多说无益,下面开始: 如果已知后三十天的股票涨跌停的情况,那么我该如何确定自己收益的最大值是多少呢?这里可以将股票每天的变化存进一个数组里,涨记为正,跌记为负,那么最后这个实际问题就转化为了求最大连续子数组的问题了,即我怎么切割这个数组使得这个数组里的值最大?这里简单的用了分治法去计算,首先将data分成2份,一份为左data

最大连续子数组和算法

求最大连续子数组和问题 sample input: -1,4,-3,6,-20,4,-2,5 sample output: 7 最容易想到的就是暴力解决方法,穷举所有连续子数组的可能性,进行比较,复杂度O(n2) 代码略 复杂度为O(n)的算法: 如果arr[0]的值大于0,将max赋值为arr[0],否则赋值为0 读取下一项,累加到sum,如果sum>0,且如果sum>max,将max更新为sum的值,如果sum<0,将sum赋值为0 重复(2)直至最后一项,所得max即为所求. 代码

【原题】求两个不相交的连续子数组的最大和

题目: 有一个整数数组n,a和b是n里两个互不相交的子数组.返回sum(a)+sum(b)的最大值. 分析: 新建两个数组left和right,left[i]表示n[0:i]的连续子数组的最大和,right[i]表示n[i:length-1]的连续子数组的最大和.left[i]+right[i+1]的最大值就是答案. int SumOfTwoSubarray(const vector<int> &n) { if (n.size() < 2) { throw exception()

经典算法——连续子数组最大和问题

Find the contiguous subarray within an array (containing at least one number) which has the largest sum. For example, given the array [?2,1,?3,4,?1,2,1,?5,4], the contiguous subarray [4,?1,2,1] has the largest sum = 6. 一.问题描述:输入一个整数数组,求数组中连续的子数组使其和最大

[算法导论]练习4.1-5最大连续子数组问题

题目:在线性时间内非递归的求数组的最大连续子数组(连续和最大的子数组). 思路:设最大子数组的和为max,起点和终点位置为s.e,正在扫描的子数组的和为add,起点和终点位置为i.j.max的初始值为-∞. 1.若数组的值全为负,则返回最大值. 2.逐个扫描数组元素,更新add.i.j的值. a.若add的值为正,则和max的值比较,如果大于max的值,更新max.s.e的值为add.i.j. b.若add的值为负,则从i到j这一段的数字只能减少子数组的和,要丢弃,add值清零并重下一个元素重新

求连续子数组的最大和

一.题目: 这是一道考的烂的不能再烂的题目,但是依然有很多公司乐于将这样的题目作为笔试或面试题,足见其经典. 问题是这样的:一个整数数组中的元素有正有负,在该数组中找出一个连续子数组,要求该连续子数组中各元素的和最大,这个连续子数组便被称作最大连续子数组.比如数组{2,4,-7,5,2,-1,2,-4,3}的最大连续子数组为{5,2,-1,2},最大连续子数组的和为5+2-1+2=8. 二.解法: 解法一:暴力求解法 /* (1) 常规方法,时间复杂度O(n*n) (2) 先从第一个元素开始向后