IT公司100题-3

题目:输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。 
例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18。 
分析:本题最初为2005年浙江大学计算机系的考研题的最后一道程序设计题,在2006年里包括google在内的很多知名公司都把本题当作面试题。由于本题在网络中广为流传,本题也顺利成为2006年程序员面试题中经典中的经典。 
如果不考虑时间复杂度,我们可以枚举出所有子数组并求出他们的和。不过非常遗憾的是,由于长度为n的数组有O(n2)个子数组;而且求一个长度为n的数组的和的时间复杂度为O(n)。因此这种思路的时间是O(n3)。 
很容易理解,当我们加上一个正数时,和会增加;当我们加上一个负数时,和会减少。如果当前得到的和是个负数,那么这个和在接下来的累加中应该抛弃并重新清零,不然的话这个负数将会减少接下来的和。基于这样的思路,我们可以写出如下代码。

#include <iostream>
using namespace std;

/////////////////////////////////////////////////////////////////////////////
// Find the greatest sum of all sub-arrays
// Return value: if the input is valid, return true, otherwise return false
/////////////////////////////////////////////////////////////////////////////
bool FindGreatestSumOfSubArray
(
      int *pData,           // an array
      unsigned int nLength, // the length of array
      int &nGreatestSum     // the greatest sum of all sub-arrays
)
{
      // if the input is invalid, return false
      if((pData == NULL) || (nLength == 0))
            return false;
      int nCurSum = nGreatestSum = 0;
      for(unsigned int i = 0; i < nLength; ++i)
       {
             nCurSum += pData[i];
            // if the current sum is negative, discard it
            if(nCurSum < 0)
                   nCurSum = 0;

            // if a greater sum is found, update the greatest sum
            if(nCurSum > nGreatestSum)
                   nGreatestSum = nCurSum;
       }
      // if all data are negative, find the greatest element in the array
      // if(nGreatestSum == 0)
      //  {
      //        nGreatestSum = pData[i][0];
      //       for(unsigned int i = 1; i < nLength; ++i)
      //        {
      //             if(pData > nGreatestSum)
      //                    nGreatestSum = pData;
      //        }
      //  }

      return true;
} 

int main()
{
      int iarray[] = {1,-2,3,10,-4,7,2,-5};
      int sum = 0;
      int length = 8;
      bool result = FindGreatestSumOfSubArray(iarray, length, sum);
      cout << "the max sum is: " << sum << endl;
}

讨论:上述代码中有两点值得和大家讨论一下: 
·         函数的返回值不是子数组和的最大值,而是一个判断输入是否有效的标志。如果函数返回值的是子数组和的最大值,那么当输入一个空指针是应该返回什么呢?返回0?那这个函数的用户怎么区分输入无效和子数组和的最大值刚好是0这两中情况呢?基于这个考虑,本人认为把子数组和的最大值以引用的方式放到参数列表中,同时让函数返回一个函数是否正常执行的标志。 
·         输入有一类特殊情况需要特殊处理。当输入数组中所有整数都是负数时,子数组和的最大值就是数组中的最大元素。

http://wdp107.iteye.com/blog/443033

IT公司100题-3,布布扣,bubuko.com

时间: 2024-10-10 21:29:48

IT公司100题-3的相关文章

IT公司100题-15-求二元查找树的镜像

问题描述: 输入一颗二元查找树,将该树转换为它的镜像树,即对每一个节点,互换左右子树. 例如输入: 6/    \4     12/ \   /   \2  5 8   16 输出: 6/     \12     4/   \   / \16  8 5  2 定义二元查找树的结点为: typedef struct BSTree { int data; BSTree* left; BSTree* right; } Node; 分析: 方法1:递归交换左右子树. // 15_1.cc #includ

IT公司100题-14-排序数组中和为给定值的两个数字

问题描述: 输入一个升序排序的数组,给定一个目标值target,求数组的两个数a和b,a+b=target.如果有多个组合满足这个条件,输出任意一对即可. 例如,输入升序数组[1, 3, 4, 5, 13, 17]和目标值20.输出3和17. 分析: 最简单的办法,直接遍历,时间复杂度为O(n^2). 双下标法:low和high a[low]+a[high] < target, low++; a[low]+a[high] > target, high–; a[low]+a[high] == t

IT公司100题-12-求1+2+…+n

问题描述: 求1+2+…+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字以及条件判断语句(A?B:C). 分析: 利用类的静态变量实现: new一含有n个这种类的数组,那么该类的构造函数将会被调用n次. 代码实现: 1 // 12.cc 2 #include <iostream> 3 using namespace std; 4 5 class Object { 6 public: 7 Object() { 8 ++N; 9 Sum += N; 10

IT公司100题-13-求链表中倒数第k个结点

问题描述: 输入一个单向链表,输出该链表中倒数第k个结点.链表倒数第0个节点为NULL. struct list_node { int data; list_node* next; }; 分析: 方法1: 首先计算出链表中节点的个数n,然后倒数第k个节点,为正数n-k+1个节点. 需要遍历链表2次. 方法1代码实现: 1 // 13_1.cc 2 #include <iostream> 3 using namespace std; 4 5 struct list_node { 6 int da

IT公司100题-11-求二叉树中节点的最大距离

问题描述: 写程序,求一棵二叉树中相距最远的两个节点之间的距离. 10/     \6      14/   \   /   \4    8 12    16 分析: 二叉树中最远的两个节点,要么是根和一个叶子节点,要么是两个叶子节点. 代码实现: 1 // 11.cc 2 #include <iostream> 3 using namespace std; 4 5 typedef struct BSTreeNode { 6 int data; 7 BSTreeNode *left; 8 BS

IT公司100题-2

1 // 定义栈的数据结构,要求添加一个min 函数,能够得到栈的最小元素. 2 // 要求函数min.push 以及pop 的时间复杂度都是O(1). 3 #include <iostream> 4 #include "../data/own/c2_list.h" 5 using namespace std; 6 7 template <typename object> 8 class miniStack{ 9 public: 10 bool isEmpty(

IT公司100题-9-判断整数序列是不是二元查找树的后序遍历结果

问题描述: 输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果. 如果是返回true,否则返回false. 例如输入4, 8, 6, 12, 16, 14, 10,由于这一整数序列是如下树的后序遍历结果: 10/     \6      14/  \    /   \4   8 12    16 因此返回true. 如果输入6, 5, 8, 5, 7 ,则返回false. 分析: 在后续遍历得到的序列中,最后一个元素为树的根结点.根节点元素将数组分为两部分,左边都小于根节点,右边都大

IT公司100题-25-求字符串中的最长数字串

问题描述: 实现一个函数,求出字符串中的连续最长数字串.例如输入”12345cbf3456″,输出”12345″. 函数原型为: void conti_num_max( const char * src, char * dest); dest保存最长数字串,返回void. 分析: 遍历一遍字符串,记录起始位置和长度即可. 代码实现: 1 // 25.cc 2 #include <iostream> 3 #include <cstring> 4 using namespace std

IT公司100题-26-左旋转字符串

问题描述: 给定字符串和左旋的字符数,写程序实现字符串的左旋操作.例如对于字符串”12345678″, 左旋转4个字符后,变成”56781234″.要求时间复杂度为O(n),空间复杂度O(1). 分析: 假设字符串表示为XY,X表示需要左旋的部分,左旋后字符串表示为YX. 根据公式: 代码实现: 1 // 26.cc 2 #include <iostream> 3 #include <string> 4 #include <cstring> 5 using namesp