Discuss / JavaScript / function isPrime(n) { var re = /^.?$|^(..+?)\1+$/; return !re.test('1'.repeat(n)); }

function isPrime(n) { var re = /^.?$|^(..+?)\1+$/; return !re.test('1'.repeat(n)); }

Topic source

Swiftyxy13

#1 Created at ... [Delete] [Delete and Lock User]

大致解释一下(需要正则表达式基础知识)。这个正则表达式总共分为两部分:第一部分是^.?$,这部分用来匹配0个或1个字符(字符串必须是相同字符),对应着n为0或1,所以n不是素数(注意前面的!)。第二部分是^(..+?)\1+$,括号里的这部分(..+?)用来匹配2个、3个或者4个以及更多字符(非贪婪匹配),\1+表示刚才括号中的内容重复一次或更多次(贪婪匹配)。

所以第二部分是这样匹配的(这里我们先假设\1+也是非贪婪匹配):对于n=6,有字符串‘111111’,正则表达式先匹配两个'1'((..+?)),然后再匹配两个'1'(\1+),发现没有匹配完(还剩两个‘1’),所以(\1+)改成匹配四个'1',匹配成功,n=6不是素数(注意前面的!);那么对于n=5,有字符串‘11111’,正则表达式先匹配两个'1',然后再匹配两个'1',没有匹配完(还剩一个‘1’)。所以(\1+)改成匹配四个'1',匹配失败,回溯,接着((..+?))改成匹配三个'1',(\1+)再匹配三个'1',失败,再回溯,直到(\1+)匹配六个'1',失败,整个正则表达式匹配失败,所以n=5是素数。

这里再说一下为什么第一部分((..+?))选择非贪婪匹配,而第二部分(\1+)选择贪婪匹配。对于n=15,对应字符串'111111111111111',假如第一部分选择贪婪匹配((..+)),那么(..+)一开始就要匹配15个字符串,接着匹配14、13......,直到5才能匹配成功,而非贪婪模式下,只需要从2匹配到5就可以成功。至于第二部分为什么选择贪婪匹配,假如选择非贪婪匹配(\1+?),假如当n=55时,(..+?)匹配到五个'1'时,\1+?会先匹配1组5个'1',2组......,直到10组才能匹配成功,而在贪婪模式下,(..+)第一次就会匹配10组5个'1'(50个'1'),这样很快就能匹配成功了。


  • 1

Reply