#java #arraylist #dynamic-programming
Вопрос:
Вот код Java для поиска кратчайшего объединения элементов массива wordBank
для построения строки Terget
с использованием динамического программирования.
Пример:
Ввод: Банк слов = {«ab», «c», «d», «abc», «ad»}, Цель = «abcd».
Вывод: {«abc», «d»}.
Для этого я сохранил комбинацию элементов в виде списка массивов в хэш-карте. Однако хэш-карта не хранит значения правильно, т. Е. Значения меняются, когда я рекурсивно вызываю функцию, хотя я клонировал список массивов перед добавлением его на карту.
Есть идеи, почему это происходит?
Код хорошо работает с массивами.
static ArrayList<String> bestConstruct(String target, String[] wordBank, HashMap<String, ArrayList<String>> map) {
if(target.isEmpty())
{
return new ArrayList<String>();
}
if(map.containsKey(target))
return map.get(target);
ArrayList<String> shortestCombination = null;
for (String word : wordBank) {
if(target.startsWith(word)) {
String newTarget = target.substring(word.length(), target.length());
ArrayList<String> combination = bestConstruct(newTarget, wordBank, map);
if(combination != null) {
combination.add(word);
if(shortestCombination == null || combination.size() < shortestCombination.size())
shortestCombination = (ArrayList<String>)(combination.clone());
}
}
}
map.put(target, (ArrayList<String>) (shortestCombination.clone()));
return shortestCombination;
}
Комментарии:
1. Нет необходимости использовать
clone()
для arraylist. Используйте конструктор копирования:new ArrayList<>(combination)
.2. Я сделал то же самое, но все равно это не работает
3. «значения меняются, когда я рекурсивно вызываю функцию» можете ли вы показать пример?
Ответ №1:
Проблема заключается во взаимодействии между этими линиями:
if(map.containsKey(target))
return map.get(target);
и
ArrayList<String> combination = bestConstruct(newTarget, wordBank, map);
if(combination != null) {
combination.add(word);
Если вы возвращаете список с памятью, вы обновляете его, прежде чем клонировать.
В общем, не полагайтесь на то, что звонящие «поступят правильно»: если вы не хотите, чтобы список на карте обновлялся, сделайте копию самостоятельно, прежде чем возвращать его:
if(map.containsKey(target))
return new ArrayList<>(map.get(target));
Возможно, вам также потребуется обработать случай, когда строка не может быть создана из банка слов.
Комментарии:
1. что вы имели в виду, говоря «не полагайтесь на то, что звонящие будут поступать правильно»? Вы имеете в виду, потому что они передают ссылки?
2. @Elahe Я имею в виду, что если вы хотите убедиться, что вызывающий абонент не вносит изменений в списки, хранящиеся на карте, не давайте им список, хранящийся на карте. Устраните их выбор поступить неправильно.