提问人:Jeff 提问时间:10/26/2009 最后编辑:IAdapterJeff 更新时间:10/26/2009 访问量:1728
简单的 Java 列表问题
Simple Java List Question
问:
我应该创建一个迭代方法拉伸,该方法将正数 n 作为参数,并返回一个新的 ListItem 开始一个列表,其中原始列表中的每个数字都重复了 n 次。例如,如果原始列表为 ( 6 7 6 9 ),参数值为 2,则返回的新列表为 ( 6 6 7 7 6 6 9 )。
我已经有一个列表项构造函数,该构造函数具有该节点的值和对下一个节点的引用:
ListItem(int number, ListItem next) {
this.number = number;
this.next = next;
}
我的代码如下所示:
public ListItem stretch(int n) {
//make an array of list items that is n times bigger than the original one.
ListItem[] newList = new ListItem[this.length() * n];
//Then loop through the old list one value at a time. At each value do a second loop n times to stretch
int index = 0;
int counter = 0;
for(int i = 0; i < this.length(); i++){
while(counter++ < n){
newList[index++] = this[i];*************************
}
return newList;****************
}
}
有两个问题点,我把它们放在了星号上。我应该返回一个列表项,但 NewList 是一个数组。 我不确定第一个星号行有什么问题。
任何帮助/指导将不胜感激。
答:
作业?
看起来你应该构建一个链表,但你正在构建一个 ListItems 数组。ListItems 数组还不错,但需要使每个 ListItem 的下一个值指向列表中的下一项。
然后,函数的最后一行将返回列表中的第一项。
评论
第一个星号行肯定是错误的,但如果你仔细想想,这不是你的问题:你一开始就没有被要求返回一个数组。
如果你考虑一下你的输入到底是什么样子,那么关于如何返回 ListItem 的问题应该会自行解决:拿一张纸,画出来,你就会明白为什么返回一个列表项就足够了,以及在 ListItem 上做什么才能使每个项目加倍。
第一行的问题在于,由于不是数组,因此不能为其下标()。如果没有关于你的班级的更多细节,我无法帮助你解决这个问题。你在做一个链表吗?this
[i]
ListItem
对于返回值,您可能希望返回数组中的第一项。如果是这样,请将其更改为 。如果要返回数组,请更改函数以返回数组,如下所示: .return newList[0]
public ListItem[] stretch(
解决这个问题的最好方法是画一些图画。然后尝试将问题分解为子问题。让我们从一个简单的案例开始:长度为 2 的列表:
ListItem two = new ListItem(1, ListItem(2, null));
这是一张图片
two = ( number == 1
( next == ( number == 2
( next == null
这是另一张图片:
+---+ +---+ The "/" here is the "null" above, which terminates the list. | 1 |->| 2 |-/ +---+ +---+
可以这样想:列表由第一个 ListItem 组成,它通过“next”指向列表的其余部分。空列表为 null,最后一个 ListItem 的“next”始终为空。(空)。
现在,当我们被要求“延伸”一个列表时,到底发生了什么?比如说,2?
好吧,空列表很容易,它不会改变。但它也无关紧要,因为在您使用的语言中会以糟糕的方式结束。长度 1 的列表是我们最简单的实际情况:null.stretch()
我们有:
we have we want +---+ +---+ +---+ | 1 |-/ | 1 |-->| 1 |-/ +---- +---+ +---+
好吧,这并不难。我们已经有一个长度为一的列表。我们需要做的就是将它挂在新 ListItem 的下一个位置,我们将得到一个长度为 2 的列表。显然,我们需要能够将某些内容添加到现有列表中。将它添加到前面是最简单的,因此我们将为此定义一个小助手:
ListItem addItemToFront(int number) {
return new ListItem(number, this);
}
好了,现在让我们把它编码起来,把它命名为 stretchFirstItemByOne:
ListItem stretchFirstItemByOne() {
return this.addItemToFront(this.number);
}
你会看到我在这些例子中经常使用 this.something(), 虽然没有必要。我只是想澄清这一点 这些是对当前对象 (this) 的方法调用。
但是,假设我们想伸展一些更大的 n?你已经尝试过 - 有点不幸 - 使用上面的for循环。你可以这样做。但我会以不同的方式去做。
ListItem stretchFirstItem(n) {
if (n == 1) // stretching to length 1 means nothing
return this; // to do. just return this.
else {
// well, if we stretch our item to length n-1 first
// then all we have to do is stretch it by one and
// we're done.
return this.stretchFirstItem(n-1).stretchFirstItemByOne();
}
}
停下来想一想那个。如果遇到问题,请将其重写为 for 循环。
你可能会说,这一切都很好,但它只处理长度为 1 的列表。多么真实,多么真实。
假设您有一个长度为 3 的列表,并且您想将其拉长 2。
+---+ +---+ +---+ ( | 1 |->| 2 |->| 3 |-/ ).stretch(2) +---+ +---+ +---+
艰难?好吧,我们至少可以开始了。如果列表只有一个项目,我们知道如何处理事情:
ListItem stretch(int n) {
ListItem restOfList = this.next;
if (restOfList == null) { // this list has length one
return this.stretchFirstItem(n);
} else {
// if we had the rest of the list stretched, then we could
// add this.number to the front of this stretched list, stretch
// that first item and then we'd be done.
}
}
嘿,但是 stretch 不应该为我们做这件事吗,你知道,拉伸整个列表吗?我们不能用它来拉伸列表的其余部分,这样我们就可以做简单的部分并拉伸第一项吗?但是我们甚至还没有写完伸展 -- 我的意思是-- 它不起作用。这不可能那么容易,不是吗?可以吗?
ListItem stretch(int n) {
ListItem restOfList = this.next;
if (restOfList == null) { // this list has length one
return this.stretchFirstItem(n);
} else {
return restOfList //-------------------------
.magic(...) // Left as an exercise for
.moreMagic(...) // the reader.
.zyzzy(...); //-------------------------
}
}
评论