以编程方式识别数字列表中的“序列”

时间:2012-10-10 19:33:46

标签: math coldfusion sequences

我需要识别 if 数字列表是否按照真实顺序。特别是5的序列。

示例1:

  • (原创系列)1,3,4,67,43,20
  • (有序系列)1,3,4,20,43,67
  • 是5的序列吗? FALSE

示例2

  • (原创系列)147,10,143,432,144,23,145,146
  • (有序系列)10,23,143,144,145,146,147,432
  • 是5的序列吗? TRUE(即143-147)

目前 - 我遍历有序列表,并检查当前号码是否等于最后一个号码+1,并保留一个计数器。这有效,但我很好奇是否有更好的方法以数学方式或以编程方式执行此操作。

<cfscript>
_list1 = [1,3,4,67,43,20]; // should evaluate to FALSE
_list2 = [147,10,143,432,144,23,145,146]; // should evaluate to TRUE

_list = _list2; // switch list in one place - test purposes only.
_seq = 1; // sequence counter
_cap = ''; // value of the upper most number of the sequence
_msg = 'There is not a consecutive sequence of 5.'; // message to user

// sort the array smallest to largest 
arraySort( _list, 'numeric' ); 

// loop the array - compare the last number with the current number 
for ( i=2; i LTE arrayLen( _list ); i++ ) {
    _last = _list[i-1]; // the LAST number - we started at the second element, so we shouldn't error.
    _this = _list[i]; // this current number
    // compare the two numbers
    if ( val( _this ) EQ val( _last ) + 1 ) {
        _seq = _seq + 1; // increment our sequence
        _cap = _this; // set the top number
    }
}

// re-set the message if we meet some threshold (5) is hardcoded here 
if ( val( _seq ) GTE 5 ) {
    _msg = 'Sequence of ' & _seq & ' to ' & _cap;
}

// write the message 
writeoutput( _msg );    
</cfscript>

4 个答案:

答案 0 :(得分:2)

对于性能,我会说你的循环包装在IF语句中,首先检查至少有5个元素;没有点循环4个元素。

然后我会说,如果'seq'= 5,在循环内做一个检查,并立即退出循环(除非你实际上需要找出序列的长度,如果它大于5)。

你可能会考虑另外一件事。在循环之前,您可以比较列表的第一个元素和列表的最后一个元素。如果它们之间的差异小于5,则完全没有必要进行循环。虽然根据您的数据看起来这可能不太可能发生。

答案 1 :(得分:1)

听起来你想要了解更多关于算法时间复杂度(https://en.wikipedia.org/wiki/Time_complexity)的内容。

您当前的算法首先进行排序然后迭代所有元素。要确定算法的时间复杂度,我们首先要知道Coldfusion的排序算法的时间复杂度。由于Coldfusion委托给Java,Java Arrays使用QuickSort算法,我们知道算法的排序部分需要n*log(n)时间。迭代数组的算法的第二部分需要n次。将这两个时间复杂性加在一起,我们得到n+(n*log(n))

在分析算法的时间复杂度时,我们只关注最慢的部分:n*log(n)。因此,Big O时间复杂度为O(n*log(n))

这是什么意思?解决方案的排序部分是最糟糕的部分。如果您可以在不进行排序的情况下解决问题,那么您可以提高应用程序的速度 - 假设您的新解决方案没有做任何比排序需要更多时间的事情。

答案 2 :(得分:0)

我会在序列中创建一个Array,然后比较Array。这是一个很好的例子:link

答案 3 :(得分:0)

我在这里提出这个答案是因为我需要一个函数来输出一系列数字,其中任何内部序列的序列都超过2个连字符(即1,3,4,5,71,3-5,7)并且没有'在其他任何地方快速找到它。你的代码看起来不再是我的了,所以我的帮助可能对你不利,尽管它可以回答你的问题,因为活跃的cfreturn提供了最长的序列(你可以将你的5楼作为比较)。(我的评论out cfreturn给出了我所需的内部序列缩写:

<cffunction name="fNumSeries" output="1" hint="pass in sorted array, get count of longest sequence">
<cfargument name="raNums" required="1" type="array">
<cfset numHold=raNums[1]>
<cfset isSeq="">
<cfset hasSeq=0>
<cfsavecontent variable="numSeries">
<cfloop from="1" to="#arraylen(raNums)#" index="idxItem">
    <cfif idxItem eq 1>#raNums[1]#<!--- always output the first --->
    <cfelse>
        <!--- if in a sequence and not the last array element, no output --->
        <cfif numHold+1 eq raNums[idxItem] and idxItem neq arraylen(raNums)>
            <!--- capture the first value of the sequence --->
            <cfif len(isSeq) eq 0><cfset isSeq=numHold></cfif>
        <cfelseif len(isSeq)><!--- was in sequence but no longer --->
            <!--- if more than 2 in a row, show as sequence (n-n) --->
            <cfif idxItem eq arraylen(raNums) and raNums[idxItem] gt isSeq+1>
                - #raNums[idxItem]#
                <cfif hasSeq lt numHold - isSeq+1><cfset hasSeq=numHold - isSeq+1></cfif>
            <cfelseif raNums[idxItem] gt isSeq+3>
                - #numHold#, #raNums[idxItem]#
                <cfif hasSeq lt numHold - isSeq+1><cfset hasSeq=numHold - isSeq+1></cfif>
            <!--- otherwise show the 2nd (held) sequential value and current array value --->
            <cfelse>, #isSeq+1#, #raNums[idxItem]#
            </cfif>
            <cfset isSeq="">
        <cfelse>, #raNums[idxItem]#<!--- not in sequence --->
        </cfif>
    </cfif>
    <cfset numHold=raNums[idxItem]>
</cfloop>
</cfsavecontent>
<!--- <cfreturn replace(numSeries, " ,", ",", "all")> --->
<cfreturn hasSeq>
</cffunction>