相关题目

1. 50个灯,有50个按钮,编号为1,2,3……50.刚开始灯全部是熄的,现在依次按按钮,每次按到按钮i,i的倍数编号的灯就变一下状态,问到最后开了几盏灯。

  对于一个数,有n个约数就被操作了n次。n为奇数就为亮,偶数就为熄灯。i=n*m,除非这个数是某个约数的平方,否则约数互不相同且成对出现,故最后亮的灯的编号是 1 4 9 16 25 49

2. 利用两个heap维持中位数

  假设这个中位数是m,对于所有 x<m 存在一个(Top1最大)最大堆中(保持<m的元素的最大值),x>m存在一个(top1最小)最小堆中。

  来了一个新的元素x,如果 x < m,则插入到最大堆中,如果>=m,则插入到最小堆中,如果两个堆的高度差大于2,则将中位数插入到数量小的哪一个heap中,并从数量多得那个head取出根节点作为中位树,同时调整两个堆。

   但是在求TopK大/小的时候,maxheap维持最大数,minheap维持最小数。求TopK大的时候,用的是最小堆,求TopK小的时候,用的是最大堆。比如在求TopK大的时候,维持一个最小堆,意思就是维持当前heap中最小的元素,对于一个新来的数,如果小于根节点,直接舍弃,大于根节点,则删除根节点,并插入这个节点,重新调整堆。

3. 二叉树遍历的非递归实现

  前序遍历(根左右)

      a. 将根节点r(不为空)进栈,然后出栈,输入值

      b. 如果r->rightchild不为空,则将r->rightchild进栈(因为rightchild一般是最后一个出)

      c. 如果r->leftchild不为空,对这个节点重复a b c 过程

          如果r->leftchild为为空,则从栈中弹出一个节点输出

  中序遍历(左根右)

      a. 将根节点r(不为空)进栈

      b. 如果r->leftchild不为空,则一直找到r-leftchild为空,并将路径上的点进栈

          出栈,输入值,对于这个节点,

      如果右子树为空,继续出栈,如果右子树不为空,对右子树重复上述过程。

   后续遍历(左右根),需要一个额外的vistied[]数组

      a. 将根节点进栈

      b. 如果r->leftchild不为空,则一直找到r-leftchild为空,并将路径上的点进栈

      c. 取出stack顶的节点(不是pop)

          如果该节点的右子树为空,则pop

          如果该节点右子树不为空,但是已经被访问过,则pop

          如果该节点右子树不为空,同时也没有被访问过,则对右子树重复上述操作。

   参考:http://blog.csdn.net/hitwhylz/article/details/14223781

4. 1 ~ n 中二进制有多少个1

  思路一:对每个1~n中的每个数字,if( x%10 ==1 ) { count++; } x = x / 10

  思路二:采用递归,1 - 21345 可能分解成 1 - 1345 和 1346 - 21345,首先求1346 - 21345中1的个数,再递归求1 - 1345中1的个数。

  对于前面,考虑,length 是 n 的位数

    1. 第一位不为1:则带来的1的个数 pow(10,length - 1)

    2. 第一位不为1:带来的1的个数 atoi(strN+1) + 1

    其它的情况:1出现在次高位:(length -1)× pow(10,length-2)× first

5.  最大连续乘积子串:给一个浮点数序列,取最大乘积连续子串的值,例如 -2.5,4,0,3,0.5,8,-1,则取出的最大乘积连续子串为3,0.5,8

  用DP求解,用Max来表示以a结尾的最大连续子串的乘积值,用Min表示以a结尾的最小的子串的乘积值,那么状态转移方程为:
      Max[i] = max{a, Max[i-1]*a, Min[i-1]*a} 因为序列中有负数,所以要考虑 Min[i-1]*a 的情况

  Min[i] = min{a, Max[i-1]*a, Min[i-1]*a}

  Max[1]=Min[1]=a[1]

  此题还有一个变形,给定一个长度为N的整数数组,只用乘法,不用除法,计算任意(N-1)个数的组合中乘积最大的一组,并写出时间复杂度。

  s[i] : i 之前的所有数乘积

  t[i] : i 之后的所有数乘积,都包括i

  max{p[i] = s[i-1] * t[i-1]}

   还可以通过分析,进一步减少计算量。假设N个整数的乘积为P,针对P的正负性进行如下分析(其中,AN-1表示N-1个数的组合,PN-1表示N-1个数的组合的乘积)。
  1. P为0 : 那么,数组中至少包含有一个0。假设除去一个0之外,其他N-1个数的乘积为Q,根据Q的正负性进行讨论:

Q为0
说明数组中至少有两个0,那么N-1个数的乘积只能为0,返回0;
Q为正数
返回Q,因为如果以0替换此时AN-1中的任一个数,所得到的PN-1为0,必然小于Q
Q为负数
如果以0替换此时AN-1中的任一个数,所得到的PN-1为0,大于Q,乘积最大值为0。

     2.    P为负数

根据“负负得正”的乘法性质,自然想到从N个整数中去掉一个负数,使得PN-1为一个正数。而要使这个正数最大,这个被去掉的负数的绝对值必须是数组中最小的。我们只需要扫描一遍数组,把绝对值最小的负数给去掉就可以了。

      3.    P为正数

     如果数组中存在正数值,那么应该去掉最小的正数值,否则去掉绝对值最大的负数值。

 

posted on 2015-06-04 10:50  keketse  阅读(134)  评论(0编辑  收藏  举报

导航