求数组插值——复杂度为O(n)的快速算法

一、问题描述

令A[1...n]是一个由n个数组成的数组,定义为数组A的插值,其中|a|

表示a的绝对值。设计一个求数组插值的算法(用伪码描述)并分析算法的时间复杂度。

二、解决方案

核心思想:

将求数组差值问题转换为熟知的求数组最大连续子序列和问题。

实现过程:

数组A有n个元素如下:[A0,A1,A2,A3,...,An],我们不妨先做一次转换,即创建新的数组B,B中有n-1个元素,分别是:

B0=A0-A1;

B1=A1-A2;

B2=A2-A3;

······

Bn-1=An-1-An-2;

假设数组A的差值为|Ai-Aj|,那么,对应的,|Ai-Aj|=|Bi + Bi+1 +...+ Bj-1|,显然,求数组A的差值问题就被我们转换成了求数组B的最大连续子序列和的绝对值的问题。

而通过动态规划,我们能够实现算法复杂度为O(n)。

过程伪码(JAVA代码):

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ArrayList<Integer> A = new ArrayList<Integer>(Arrays.asList(A1,A2,···,An));
		ArrayList<Integer> B = new ArrayList<Integer>();                //创建数组
		for (int i = 0 ; i < A.size()-1 ; i++){
			B.add(A.get(i) - A.get(i+1));
		}                                                                                        //向数组B中添加元素Ai-Ai+1
		//动态规划实现过程
		int maxhere,maxsum;
		maxhere=maxsum=B.get(0);
		for (int i = 1 ; i < B.size() ; i++){
			if (Math.abs(maxhere+B.get(i)) < Math.abs(B.get(i))){
				maxhere = B.get(i);
			}                                                                                    /*如果前面位置到A[i]的最大子序列和
			绝对值反而比|A[i]|要小,则以当前位置i结尾的最大子序列和为A[i]*/
			else{
				maxhere += B.get(i);
			}                                                                                   /*如果前面位置到A[i]的最大子序列和
			绝对值要比之前位置的更大,则取最大子序列和绝对值为两者之和*/
			if (Math.abs(maxhere) > Math.abs(maxsum)){
				maxsum = maxhere;
			}                                                                                     //更新最大子序列和的绝对值
		}
		System.out.println(Math.abs(maxsum));
	}

算法复杂度分析:

创建数组B的算法复杂度为O(n-1),实现最大子序列和绝对值的算法复杂度为O(n-1),则总体算法复杂度为O(n-1)+O(n-1)=O(n),属于比较快速的算法。

|萌新想法,如有疏漏,望请大佬指正!

时间: 2024-10-10 18:17:19

求数组插值——复杂度为O(n)的快速算法的相关文章

编程之美5:求数组中最长递增子序列

最近楼楼被男朋友带着玩dota,有点上瘾,终于在昨天晚上作出了一个重大的决定,shift+delete删掉warIII文件夹,从此退出dota的明争暗斗.不过最近看男票已经将战场从11转到了topcoder,嗯,这是个好现象,希望楼楼也能跟着玩儿起来. 理想是美好的,唉,可是楼主还在编程之美的初级阶段啊.话不多说了,希望自己加油加油再加油!!(^o^)/~ 今天要看的一道题目是求数组中最长递增子序列. 题目简介: 写一个时间复杂度尽可能低的程序,求一个一维数组(N)个元素中的最长递增子序列的长度

写一个方法求数组中的最大值,最小值,总和以及平均值。

class Program { /// <summary> /// 求数组中的最大值,最小值,总和以及平均值. /// </summary> /// <param name="nums">输入一个数组</param> /// <returns>返回一个新的数组(max,min,sum,avg)</returns> public static int[] GetMaxMinSumAvg(int[] nums) { i

class 3 求数组中的最大值(单元测试)

1.问题引出: int Largest(int list[], int length) { int i,max; for(i = 0; i < (length – 1); i ++ ) { if(list[i] > max) { max=list[i]; } } return max; } 由此段程序编写一个正确的程序实现求数组的最大值. #include <iostream> using namespace std; int Largest(int list[],int leng

[LeetCode] Find Peak Element 求数组的峰值

A peak element is an element that is greater than its neighbors. Given an input array where num[i] ≠ num[i+1], find a peak element and return its index. The array may contain multiple peaks, in that case return the index to any one of the peaks is fi

《github一天一道算法题》:分治法求数组最大连续子序列和

看书.思考.写代码! /*************************************** * [email protected] * blog: http://blog.csdn.net/hustyangju * 题目:分治法求数组最大连续子序列和 * 思路:分解成子问题+合并答案 * 时间复杂度:O(n lgn) * 空间复杂度:O(1) ***************************************/ #include <iostream> using nam

算法题:求数组中最小的k个数

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 题目:输入n个整数,找出其中最小的k个数. <剑指offer>给出了两种实现算法: 算法1:采用Partition+递归法,该算法可以说是快速排序和二分查找的有机结合.算法的时间复杂度为O(n),缺点在于在修改Partition的过程中会修改原数组的值. 算法2:采用top-k算法.如果要找最小的K个数,我们才用一个含有K个值的大顶堆:如果要找最大的K个数,我们采用小顶堆.该算法的时间复杂度为O(nlogK),是一种比较好的算法,启发于堆排序

1、打印二进制机器码,程序内存分析,大端序小端序,指针数组,数组指针,数组的三种访问方式,typedef,#if-0-#endif,求数组大小,括号表达式

 1.打印二进制机器码(分别表示32位的和64位的) #include <stdio.h> /*按照8位的长度打印一个数值*/ void dis8bit(char val) { int bit = 8; while(bit--) { if(1<<bit&val){ printf("1"); } else { printf("0"); } if(!(bit%4)) printf(" "); } putchar(1

用C随机产生的正整数存到数组中,并求数组中的所有元素最大值、最小值、平均值以及各元素之和,及第二大值。

用 C 求一组随机数的第二大值,不能通过对整体排序求得 1 随机产生20个[10 , 50]的正整数存到数组中,并求数组中的所有元素最大值.最小值.平均值以及各元素之和,及第二大值.        int a[20];    int sum = 0; //存储数组元素的和    //为数组赋值    printf("数组中的元素为:\n ");    for (int i = 0; i < 20; i ++) {        a[i] = arc4random() % 41 +

求数组中和为给定值的任意两个数

转载请注明出处:http://blog.csdn.net/ns_code/article/details/24933341     题目: 输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字.要求时间复杂度是O(n).如果有多对数字的和等于输入的数字,输出任意一对即可. 例如输入数组1.2.4.7.11.15和数字15.由于4+11=15,因此输出4和11.     思路: 最直接的做法是暴力法,两个for循环,时间复杂度为O(n*n),但是这样没有充