对于一个字节(8bit)的变量,求其二进制表示中“1”的个数,要求算法的执行效
率尽可能地高。
2、
求子数组的最大和
题目:输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。
例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18。
因为是O(N)的复杂度,因此需采用的DP的思想,记录下当前元素之和(为其最优状态,既最大),将其与目前所得的最大和比较,若大于则更新,否则继续。状态的累加遵循这个过程:如果当前和小于0,则放弃该状态,将其归零。
答案:
关于数组中最长递增子序列,题目如下:
写一个时间复杂度尽可能低的程序,求一个一维数组(N个元素)中最长递增子序列的长度。
例如在序列1,-1,2,-3,4,-5,6,-7中,其最长的递增子序列的长度为4(如1,2,4,6),从该书给的例子我们可以知道的是其最长的递增子序列可以不连续的。
解法一:
根据无后效性的定义,各阶段按照一定的次序排列好之后,对于某个给定阶段的状态来说,它以前各阶段的状态无法直接影响它未来的决策,而只能间接地通过当前状态来影响,如以下目标串:
1,-1,2,-3,4,-5,6,-7
当i=1时,显然,最长的递增序列为(1),序列长度为1.
当i=2时,由于-1<1,因此,必须丢弃第一个值然后重新建立串,当前的递增序列为(-1),长度为1.
当i=3时,由于2>1,2>-1,因此,最长的递增序列为(1,2),(-1,2),长度为2,在这里,2前面是1还是-1对求出后面的递增序列没有直接影响。
假设在目标数组array[]的前i个元素中,最长递增子序列的长度为LIS[i],那么用动态规划可以推出以下公式:
LIS[i+1]=max{1,LIS[k]+1},array[i+1]>array[k],for any k<=i
即如果array[i+1]大于array[k],那么第k+1个元素可以接在LIS[k]长的子序列后面构成一个更长的子序列,同时array[i+1]本身至少可以构成一个长度为1的子序列。
从作者的分析角度,我们可以用树的结构来分析,如图:
代码实现:
#include
#include
#include
using namespace std;
int Max(int *a,int len)
{
int max=1;
for(int i=0;i
if(max
max=a[i];
return max;
}
int LIS(int *a,int len)
{
int *LISAry=new int[len];
for(int i=0;i
{
LISAry[i]=1;
//遍历寻找最长递增序列,找到后若比当前i的最长递增序列大,就更改
for(int j=i-1;j>=0;j--)
if(a[i]>a[j]&&LISAry[i]
LISAry[i]=LISAry[j]+1;
}
return Max(LISAry,len);
}
int main()
{
int a[8]={1,-1,2,-3,4,-5,6,-7};
int len=sizeof(a)/sizeof(int);
cout <
//随机测试
for(int i=0;i
{
for(int j=0;j
{
a[j]=rand()%100+1;
cout<