Лучший способ подойти к этой проблеме - нарисовать несколько фотографий. Затем попытайтесь разбить проблему на подзадачи. Давайте начнем с простого случая: список длины 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». Пустой список, затем является нулевым, а «следующий» из последнего ListItem всегда пуст. (ноль).
Теперь, что происходит, когда нас просят «растянуть» список? Скажем, на 2?
Ну, пустой список прост, он не меняется. Но это также не имеет значения, так как null.stretch()
плохо закончится на используемом вами языке. Список длины 1, то наш простейший практический случай:
мы имеем:
we have we want
+---+ +---+ +---+
| 1 |-/ | 1 |-->| 1 |-/
+---- +---+ +---+
Хорошо, что это не так трудно. У нас уже есть список длинной. Все, что нам нужно сделать, отключить его от следующего списка ListItem, и у нас будет список длиной два. Ясно, что нам нужна возможность добавить что-то в существующий список. Добавление его на фронт простой, поэтому мы определим маленький помощник для этого:
ListItem addItemToFront(int number) {
return new ListItem(number, this);
}
Хорошо, теперь давайте код, который и называют его stretchFirstItemByOne:
ListItem stretchFirstItemByOne() {
return this.addItemToFront(this.number);
}
Вы см. мне использовать this.something() много в этих примерах, , хотя это не обязательно. Я просто пытаюсь понять, что это вызовы метода для текущего объекта (это).
Но, предположим, что мы хотим, чтобы растянуть некоторые больше п? Вы уже несколько раз пытались использовать цикл 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, если у вас возникнут проблемы.
Это все очень хорошо, вы могли бы сказать, но он обрабатывает списки только одной длины. Как верно, насколько верно.
Предположим, что у вас есть список длиной 3 и вы хотите, чтобы растянуть его на 2.
+---+ +---+ +---+
(| 1 |->| 2 |->| 3 |-/).stretch(2)
+---+ +---+ +---+
Tough? Ну, мы можем начать хотя бы. Мы знаем, как обращаться с вещами, если список содержит только один элемент:
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.
}
}
Эй, но не простирания должен сделать это для нас, вы знаете, растягивать целые списки? Не могли бы мы использовать это, чтобы растянуть остальную часть списка, чтобы мы могли сделать легкий бит и растянуть первый элемент? Но мы еще не закончили писать растяжение - я имею в виду - это не работает. Это не могло быть так просто, не так ли? Не могли бы?
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(...); //-------------------------
}
}
Какой это тип? не знаете, почему вы выполняете подзаголовок. –
Что означает Сан Хасинто, это то, что [i]; часть почти наверняка ошибается. – theycallmemorty