441人阅读 评论(0)

# 最大连续子序列问题

//假设给定序列：a1,a2,...,aK
maxsum=0; // 最大的连续子序列的和
for(int i=0; i<K; i++){
tmpSum=0;
for(int j=i; j<K; j++){
tmpSum += a[j]
if(tmpSum > maxsum){
maxsum = tmpSum;
}
}
}

int MaxSubSum(const int A[], int Left, int Right)
{
int MaxLeftSum,MaxRightSum;
int MaxLeftBorderSum,MaxRightBorderSum;
int LeftBorderSum,RightBorderSum;
int mid,i;

if(Left == Right) // 处理只有一个元素的子序列
{
if(A[Left] > 0)
return A[Left];
else // 对于小于等于0的元素，
return 0;
}

mid= (Left + Right)/2;
// 情况1
MaxLeftSum = MaxSubSum(A,Left,mid);
// 情况2
MaxRightSum = MaxSubSum(A,mid+1,Right);

// 情况3
MaxLeftBorderSum = 0;
LeftBorderSum = 0;
for(i = mid;i >= Left;i--)// 求解最大序列的左边部分
{
LeftBorderSum += A[i];
if(LeftBorderSum > MaxLeftBorderSum)
MaxLeftBorderSum = LeftBorderSum;
}

MaxRightBorderSum = 0;
RightBorderSum = 0;
for(i = mid+1;i <= Right;i++)// 求解最大序列的右边部分
{
RightBorderSum += A[i];
if(RightBorderSum > MaxRightBorderSum)
MaxRightBorderSum = RightBorderSum;
}

return Max(MaxLeftSum,MaxRightSum,MaxLeftBorderSum + MaxRightBorderSum); // 返回三种情况中最大的结果
}

int maxSubSeq(int[] ary){
int maxsum=0;
int localSum=0;
for (int i=0; i<ary.length; ++i){
localSum += ary[i];
if(localSum > maxsum){
maxsum= localSum;
}else if (localSum < 0){
localSum=0; // 不考虑 ai~aj中的元素作为子序列的开头, 其中ai>0, aj<0
}//else  => localSum >0, 就是引理2中的条件1
}
}

# 不同子序列的个数

final MaxLen = 99999;
int[] last = new int[MaxLen]; // 假设初始化为-1
int[] f = new int[MaxLen];
int n=scan.nextInt(); // read the length of the seq
for(int i=1; i<=n; ++i){
int x = scan.nextInt();
if(last[x]!=-1){
f[i] = f[i-1]*2 - f[last[x]];
}else{
f[i] = f[i-1]*2+1;
}
last[x]=i;
}

# 可作为Fibonacci数列前缀的非空子序列个数 [微软面试题]

One line with an integer n.
Second line with n integers, indicating the sequence {an}.
For 30% of the data, n<=10.
For 60% of the data, n<=1000.
For 100% of the data, n<=1000000, 0<=ai<=100000.

fibonacci 数列：
F1 = 1, F2 = 1
Fn = Fn-1 + Fn-2, n>=3

2 1 1 2 2 3

7

## 解题思路

{12},
{13},
{12 13},
{12 13 24},
{12 13 25},
{12 13 25 36},
{12 13 24 36}

f(i,j) 表示原数列中前i个数中，以Fibonacci 数列中第 j项 (从下标1开始) 作为子序列结尾元素的子序列个数.

1. 当原序列的第i个元素 a[i] 在其前的元素里没有出现过时： 原序列的第 i 项，与原序列中前 i-1 个元素以Fibonacci序列的第 j-1 项构成的子序列结合，因此 有 f(i-1, j-1)个是Fibonacci前缀新子序列。
2. 当原序列的第i个元素 a[i] 在其前的元素里出现过时：假设在原序列前 i-1 个元素中，出现过和 a[i] 相等的元素 a[i’]，其中 i’ < i. 由于a[i]是Fibonacci序列的第 j 项，a[i’]也是Fibonacci序列的第 j 项，因此 f(i-1, j) 也表示原序列前 i 个元素以a[i]作为结束元素的符合要求的子序列的个数。如果在前i-1个元素中不存在和当前元素a[i]相等的元素，该项为0.

Fibonnaci数列中前两项具有相同值，因此需要特殊处理。
a[i] == 1时：
f(i, 1) = f(i-1, 1)
f(i, 2) = f(i-1, 2) + f(i-1, 1)

## 代码如下

// 优化后的算法
java
import java.io.BufferedInputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Main {
static final int Max=1000010;
static int[] fibs=new int[Max];
static Map<Integer,Integer> indFibs = new HashMap<>();
static void init(){
fibs[0]=fibs[1]=1;
for(int i=2; ; ++i){
fibs[i]=fibs[i-2]+fibs[i-1];
indFibs.put(fibs[i], i+1);// 记录fib数在序列中的位置
if(fibs[i]>=Max)
break;
}
indFibs.put(1, 2);
}
static void display(int[] f){
for(int i=0; i<f.length; ++i){
System.out.print(f[i] +" ");
}
System.out.println();
}
static void solver(){
init();
int[] f = new int[26];
f[0]=1;
final int M = 1000000007;
Scanner scan = new Scanner(new BufferedInputStream(System.in));
int n = scan.nextInt();
for(int i=0; i<n; ++i){
int x = scan.nextInt();
if(indFibs.containsKey(x)){
int j = indFibs.get(x);
f[j] = (f[j-1]+f[j]) % M;
if(x==1){
f[1]=(f[1]+f[0]) % M;
}
}
}
scan.close();
int ans = 0;
for(int i=1; i<=25; ++i){
ans = (ans+f[i])%M;
}
System.out.println(ans);
}
public static void main(String[] args) {
solver();
}
}`

0
0

* 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场
个人资料
• 访问：26538次
• 积分：431
• 等级：
• 排名：千里之外
• 原创：11篇
• 转载：23篇
• 译文：2篇
• 评论：0条
评论排行