关于基数排序的Java实现的解释
Posted
技术标签:
【中文标题】关于基数排序的Java实现的解释【英文标题】:explanation about a Java implementation of radix sort 【发布时间】:2016-02-20 03:04:26 【问题描述】:我正在阅读和学习基数排序的 Java 实现,如下所示。如果有人能阐明pointTo
、index
和globalPtr
的逻辑含义,那就太好了。
https://www.hackerrank.com/challenges/string-similarity/editorial
private void radixSort0()
globalPtr = 0;
Arrays.fill(bucketHead, -1);
Arrays.fill(next, -1);
for (int i = 0; i < n; i++)
int value = nr0[index[i]];
if (bucketHead[value] == -1) bucketHead[value] = bucketTail[value] = globalPtr;
else bucketTail[value] = next[bucketTail[value]] = globalPtr;
pointTo[globalPtr++] = index[i];
int ptr = 0;
for (int i = 0; i < M; i++)
for (int j = bucketHead[i]; j != -1; j = next[j])
index[ptr++] = pointTo[j];
【问题讨论】:
不要发布hackerrank问题以获得答案,最好尝试一些东西并发布您的代码以进行一些修改。快乐编码 永远不要模仿那种风格来命名、(不)评论、代码、程序。简单的部分是globalPtr
:下一个要分配的索引。 hackerrank的链接需要登录——内容和lydxlx's一样吗?
谢谢@greybeard,那么pointTo的逻辑意义是什么?
(请说明github link 是否相关。)该部分是附加到单链表的末尾,使用附加级别的(去)索引。我还没有真正试图弄清楚是否需要这样做:radixSort0
中使用的许多东西都是预设的或在外面使用的。 (如果这是接近 lydxlx 的代码,globalPtr, pointTo, bucketHead, bucketTail
和 next
也可能是 radixSort0&1 的本地代码。)如果此代码的基础不是来自算法教科书,我会感到惊讶。
(我会考虑一下代码,可能是在睡了一晚之后。)
【参考方案1】:
这个radixSort0()
不是一个完整的基数排序。如果您的目标是了解基数排序,请查看其他地方。
在两种(不必要的重复)radixSort
方法中,int[] next
用于建立单链表 - 使用索引而不是引用,以及 -1 而不是 null。 (您可以不将next[some_index_depending_on value]
设置为index[i]
- 不会有列表。)int[] pointTo
可能更具描述性地命名为value
。将next&value
视为链表,在具有两个数组类型数据成员的实例中表示,作为具有成员next&value
的实例数组的替代方案。 globalPtr
是尚未在那个/那些数组/s 中分配的最小索引。
(后面的代码中明显缺少 cmets 是因为我不理解为什么任何人都应该尝试使用它来构造一个后缀数组,或者这些代码对实现该目标的贡献:随时更正和修改。) 甚至不考虑测试,Java 的处理方式可能是
private void radixSortStep(int[]nr)
List<Integer> value[] = new List[M];
for (int i = 0; i < value.length; i++)
value[i] = new ArrayList<Integer>(0);
for (int i: indexes)
value[nr[i]].add(i);
int ptr = 0;
for (int i = 0; i < M; i++)
for (int val: value[i])
indexes[ptr++] = val;
(对M
(设置为n+1)和nr1
(初始化条目未从等级复制到n
,而不是-1)有点挥手)
【讨论】:
感谢 graybeard,正在努力学习您的代码。关于 github 版本代码的另一个困惑,我查看了 github 链接中的代码,如果您能评论为什么我们不能只使用bucketTail[value] = next[bucketTail[value]]=index[i]
,并完全删除 pointTo
和 globalPrt
的使用,将不胜感激.我认为我们可以安全地使用 index[i],而不是使用 pointTo/globalPtr 来获得另一个级别的间接性。如果我错了,请随时纠正我。谢谢。
我在括号中试过:next[]
和 bucketTail[]
用于List
基础设施,只有pointTo[]
持有(索引-)值。
嗨灰胡子,喜欢你优雅的实现!同意你所有的 cmets,除了这个,“你不能只将 next[some_index_depending_on value]
设置为 index[i]
- 不会有列表。”,假设我们正在对 21 和 31 进行基数排序,目前正在对这些进行排序。 21作为头尾都插入到桶中,我们直接给桶头[1]和桶尾[1]分配它的位置(本例中为0),当我们处理31时(其位置为1,也就是值index[1]),我们应该可以将它分配给 bucketTail 的下一个,
并将bucketTail移动到31。在代码中,它是bucketTail[value] = next[bucketTail[value]] = index[i]
,或者'next[bucketTail[value]] = index[i]' + bucketTail[value]=index[i]
,这使得21 -> 31,和 31 作为尾巴。所以,我认为不使用 pointTo 和 next 是安全的。我认为不使用 pointTo 和 next 是安全的另一个原因是基于 LSD 的基数排序保留 oder。我的描述有什么问题?请随时纠正我。谢谢。
(忘记在我之前的评论中提到@LinMa)不太确定我明白你在说什么。你可以在bucketHead[value]
中保留一个值,在buckettail[value]
中保留一个第二个值,但是第三个、第七个、无数个值在哪里?【参考方案2】:
import java.io.*;
import java.util.*;
public class St
public static int calculate(String s)
char[]arr=s.toCharArray();
int length=arr.length;
int count=length;
for(int i=1;i<length;i++)
int len=length-i;
int j=0;
for(;j<len;j++)
if(arr[j]!=arr[j+i])
break;
count+=j;
return count;
public static void main(String[] args)
Scanner scanner = new Scanner( System.in );
int n=scanner.nextInt();
for(int i=0;i<n;i++)
String s=scanner.next();
System.out.println(calculate(s));
由于超时,它几乎通过了除了最后两个之外的所有测试用例,希望我的工作有助于快乐编码..
【讨论】:
感谢 SmashCode,您的回复与我的问题有何关系? :) 如果你的意思是我告诉测试用例通过的数量我也是hackerrank用户,会有添加评论按钮。 感谢 SmashCode,我认为您的代码运行速度比 SuffixArray 慢?您的代码运行 O(n^2)? 嗨 SmashCode,在我发布的原始代码中,我对这个声明特别困惑,bucketTail[value] = next[bucketTail[value]] = globalPtr
,为什么我们不能只使用bucketTail[value] = next[bucketTail[value]]=index[i]
,看不到globalPtr
的太多值?感谢您的建议。谢谢。以上是关于关于基数排序的Java实现的解释的主要内容,如果未能解决你的问题,请参考以下文章