collections - 回文检查抛出无限循环(使用迭代器和链表集合)
问题描述
我正在尝试编写一种方法来确定字符串类型的单链表是否是回文。
想法是将后半部分复制到堆栈,然后使用迭代器弹出堆栈的元素并检查它们是否与从 0 到单链表一半左右的元素相同。
但是我的迭代器方法抛出了一个无限循环:
public static boolean isPalindrome(LinkedList<String> list, Stack<String> stack ) {
int halfList = (int) Math.ceil(list.size()/2); // we get half the list size, then round up in case it´s odd
// testing: System.out.println("half of size is " + halfList);`
// copy elements of SLL into the stack (push them in) after reaching the midpoint
int count = 0;
boolean isIt = true;
Iterator<String> itr = list.iterator();
Iterator<String> itr2 = list.iterator();
System.out.println("\n i print too! ");
// CHECK!! Node head = list.element();
// LOOP: traverse through SLL and add the second half to the stack (push)
// if even # of elements
if ( list.size() % 1 == 0 ) {
System.out.println("\n me too! ");
while ( itr.hasNext() ) {
String currentString = itr.next(); // this throws an exception in thread empty stack exception
count ++;
if ( count == halfList ) stack.push(list.element());
// THIS IS THE INFINITE LOOP
System.out.println("\n me three! ");
}
}
// else, if odd # of elements
else {
while ( itr.hasNext() ) {
count ++;
if ( count == halfList -1 ) stack.push(list.element());
}
}
// Now we compare the first half of the SLL to the stack (pop off elements)
// even
if ( list.size() % 1 == 0 ) {
while ( itr2.hasNext() ) {
count ++;
if ( count == halfList +1 ) break;
int compared = stack.pop().compareTo(list.element());
if ( compared != 0) isIt = false; // if when comparing the two elements, they aren´t similar, palindrome is false
}
}
// odd
else {
while ( itr2.hasNext() ) {
count ++;
if ( count == halfList ) break;
int compared = stack.pop().compareTo(list.element());
if ( compared != 0) isIt = false;
}
}
return isIt;
}
我究竟做错了什么?
解决方案
有很多问题:
list.size() % 1 == 0
不检查大小是否均匀。正确的检查是% 2
。- 堆栈异常不会发生在您放置该注释的行上。它发生在您拥有的代码的更下方
stack.pop()
。此异常的原因是您尝试从没有更多元素的堆栈中弹出一个元素。 - 在您放置该评论的地方不会发生无限循环。它会发生在您在代码中进一步的任何其他循环中:您永远不会调用
itr.next()
oritr2.next()
,因此如果您到达那里,您将无限循环。 - 堆栈永远不会获得超过 1 个压入它的值。这是因为您有一个严格的相等条件,在迭代期间只为真一次。这不是您想要的:您希望列表的一半最终在堆栈上。这也是你得到堆栈错误的原因:你的代码的后半部分期望堆栈上有足够的项目。
push(list.element())
总是将第一个列表值推送到堆栈,而不是当前迭代的。这应该是push(currentString)
。count ++;
被放置在你的循环中一个不直观的地方。如果将该行移至循环中的最后一条语句,则更有意义。if ( count
陈述都是错误的。如果您移动count ++
到最后一个语句,那么这if
应该读取if ( count >= halfList )
偶数情况和if ( count > halfList )
奇数情况。当然,如果halfList
进行了改编会更容易,这样您就可以平等地处理奇数和偶数情况。- 您的代码的第二部分没有重置计数器,而是继续使用
count ++
. 这将使那永远不会是真的,因此这也是最终会引发异常if ( count == halfList )
的另一个原因。stack.pop()
要么你应该在开始下半场之前重置计数器(使用count = 0;
),或者更好的是,你应该检查堆栈是否为空,然后退出循环。 - 您的代码的后半部分不需要区分奇数或偶数。
- 与其设置
isIt
为 false,不如直接使用 立即退出函数,return false
因为继续迭代没有进一步的好处。 - 该函数不应将堆栈作为参数:您总是希望从一个空堆栈开始,所以这应该是一个局部变量,而不是一个参数。
- 对
Math.ceil
已经是int
.int
当两个参数都是 时,除法的结果是int
。所以要向上舍入,在除之前加 1:(list.size()+1) / 2
- 避免代码重复
当您调试代码时,这些问题中的大多数都很明显。将打印行与“我在这里”放在一起并没有太大帮助。更好的是打印变量的值,或者在检查变量的同时使用良好的调试器逐步执行代码。如果你这样做了,你就会发现上面列出的许多问题。
这是解决上述问题的代码版本:
public static boolean isPalindrome(LinkedList<String> list) {
Stack<String> stack = new Stack<String>();
int halfList = (list.size()+1) / 2; // round upwards
Iterator<String> itr = list.iterator();
while (halfList-- > 0) itr.next(); // skip first half of list
while ( itr.hasNext() ) stack.push(itr.next()); // flush rest unto stack
Iterator<String> itr2 = list.iterator();
while ( itr2.hasNext() && !stack.empty()) { // check that stack is not empty
if (stack.pop().compareTo(itr2.next()) != 0) return false; // no need to continue
}
return true;
}
推荐阅读
- numpy - numpy.linalg.eig 没有找到明显的特征向量
- php - 在编辑从数据库循环的数据期间,如何在选择选项中获取数据?
- css - 滚动时修复 ThreeJS 模型的位置
- html - 奇怪的弹性项目行为
- database - 了解填充猫鼬
- c++ - 为什么当我调用它时 QTextBrowser::clear() 不能立即工作?
- javascript - 如何将 oswald google 字体作为字体系列下拉列表中的列表应用到 tinymce 编辑器?
- c# - .Net 从 MySQL 转储文件中解析 blob 数据
- go - 如何通过 client-go 删除 k8s Jobs 及其 Pod?
- python - 为什么 plotly 函数需要 Python 和 R 中的不同数据格式来绘制 3d 曲面图?