寻找列表中最长项的长度的最有效方法是什么?

3

给定一个长度不同的单词列表,如何找到其中最长单词的长度?

例如,下面的列表应该返回6:

findMaxLen("a,set,of,random,words")

当然,这很简单...
<cffunction name="findMaxLen" returntype="Numeric">
    <cfset var CurMax = 0 />
    <cfset var CurItem = 0 />
    <cfloop index="CurItem" list="#Arguments[1]#">
        <cfif Len(CurItem) GT CurMax >
            <cfset CurMax = Len(CurItem)/>
        </cfif>
    </cfloop>
    <cfreturn CurMax />
</cffunction>

或者,稍微简短一些...
<cffunction name="findMaxLen" returntype="Numeric">
    <cfset var CurMax = 0 />
    <cfset var CurItem = 0 />
    <cfloop index="CurItem" list="#Arguments[1]#">
        <cfset CurMax = Max( CurMax , Len(CurItem) ) />
    </cfloop>
    <cfreturn CurMax />
</cffunction>


但是有没有更好的方法——更高效的方法呢?

也许有一些Java方法?将其转换为数组并按项长度排序?计算逗号之间的最大差距?


实际上,以上两个示例都可以很好地满足我的当前需求,这不是用于性能关键的东西,因此我不需要一个答案,但我认为看看人们可能会想出什么还是很有趣的...


3
我必须在这时插话:基于XML的语言是一种可憎之物 :) - Andrew Rollings
2
CFML是基于标签的,不是基于XML的。除了上面的cffunction标签外,其他标签都会让XML解析器报错。 - Peter Boughton
14个回答

11

计算逗号之间的距离。

我认为没有比这更快的方法了;它的时间复杂度是O(n),而且你无论如何都要至少查看每个字符一次(以查看是否为逗号)。

int FindLongestWord(char* str)
{
   char* lastComma = str - 1;
   int longest = 0;
   int length;
   char* pCheckChar;

   for(pCheckChar = str; *pCheckChar; pCheckChar++)
   {
      if(*pCheckChar == ',')
      {
         length = pCheckChar - lastComma - 1;
         if(length > longest)
         {
            longest = length;
         }

         lastComma = pCheckChar;
      }
   }

   // Check to see if the last word is the longest
   length = pCheckChar - lastComma - 1;
   if(length > longest)
   {
      longest = length;
   }

   return longest;
}

或者我想你也可以直接说

"a,set,of,random,words".Split(',').Max(w=>w.Length);

如果我们在玩游戏... ;]


@sfossen:为什么,你自己不能做吗?;-) - David Z
我也可以做到,但我也不想让我的答案被接受。但是,真的,我可以。老实说。 - Beska
小错误,lastComma仅在最长匹配时更新。应该放在第二个if语句下面。 - sfossen

2
在 Perl 中(假设我们有一个变量 $max 用于存储答案):
(length $1 > $max) && ($max = length $1) while "a,set,of,random,words" =~ /(\w+)/g;

或者:

(length $_ > $max) && ($max = length $_) foreach split /,/, "a,set,of,random,words";

或者:

$max = length((sort { length $b <=> length $a } split /,/, "a,set,of,random,words")[0]);

毕竟,有多种方法可以做到这一点。

编辑:我忘记了核心模块!

use List::Util 'reduce';
$max = length reduce { length $a > length $b ? $a : $b } split /,/, "a,set,of,random,words";

......它以某种方式比其他的长。哦,那好吧!

编辑2:我刚想起来map()

use List::Util 'max';
$max = max map length, split /,/, "a,set,of,random,words";

这就是我要找的东西。

编辑3:为了完整起见:

($max) = sort { $b <=> $a } map length, split /,/, "a,set,of,random,words";

我想指出的是,可能有更好的方法来完成这些任务,但我还是想把它们分享出来。 - Chris Lutz

1

这里是“简短”的 CFML 方式 - 72 个字符...

Len(ArrayMax("a,set,of,random,words".replaceAll('[^,]','1').split(',')))

另一个版本,78个字符但可以处理巨大的字符串(请查看评论)...

Len(ListLast(ListSort("a,set,of,random,words".replaceAll('[^,]','1'),'text')))

如果您使用“set”而不是“series”,则为72。 - Georg Schölly
哎呀,应该复制粘贴而不是重新输入。谢啦。 - Peter Boughton
我对CFML一无所知;它适用于任何长度的字符串吗?(例如,没有逗号的1000个字符长度的字符串)我想知道ArrayMax是否真正将111s转换为数值数据类型... - Daniel LeCheminant
你是正确的 - ArrayMax给出了最大的数字,所以它将每个字符串转换成数字,并在300到400之间某处失败了。一个类似的基于列表的排序版本(添加在上面)虽然速度非常慢,但可以处理大值 - 在大约6.6秒内处理了10,000,006。 - Peter Boughton
@Peter:我想知道“在300到400之间”是否是64位双精度浮点数的极限(大约为1.8e308)... - Daniel LeCheminant
显示剩余4条评论

1

既然有一个code-golf标签,这里是C#中的52个字符

"a,set,of,random,words".Split(',').Max(w=>w.Length);

我猜我们都想同时删除 String. - Daniel LeCheminant

0

我手头没有Python,所以无法检查这是否有效,但是...

def maxlen(x):
    return len(sorted(x.split(), key=lambda y: len(y))[1])

应该可以解决问题。


0

这难道不是最简单的吗?

<cffunction name="findMaxLen" returntype="Numeric">
    <cfset longest = 0>
    <cfloop list="#Arguments[1]#" index="w">
        <cfif len(w) gt longest>
            <cfset longest = len(w)>
        </cfif>
    </cfloop>
    <cfreturn longest>
</cffunction>

这个方法已经在原问题中发布过了。你可能错过了[code-golf]标签(现已弃用)- 包括空格在内共249个字符;-)。 - Leigh

0

Clojure: 49 字节。

(def l #(reduce max(for[x(.split%%2)](count x))))

易读版本:

(defn longest [astr sep]
  (reduce max
    (for [word (.split astr sep)]
      (count word))))

我仍在学习这门语言,所以我很想听听有哪些方法可以提高它。


0

在VC++中

int findMaxLen(const char *s)
{
    const char c = ',';
    int a = 0, b = 0;
    while(*s)
    {
        while(*s && *s++ != c)b++;
        if(b > a)a=b;
        b = 0;
    }
    return a;
}

0

在Scala中(55个字符):

",set,of,random,words".split(",").:\(0)(_.length max _)

0

我看到了代码高尔夫标签 - 这里是 Python 中的 54 个字符:

len(max("a,set,of,random,words".split(","), key=len))

尝试运行max(map(len,"a,set,of,random,words".split(",")))。52 - recursive
并不是指最少字符的意义,但也可以。 :) 你能通过在key前省略空格来节省一个字符吗? - Peter Boughton
实际上,@recursive,那是48个字符。 :-) - Patrick McElhaney
@recursive - 你赢了我 - 非常棒! - Andrew Hare

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接