Реверс массива типа String с сохранением длины элементов
Только изучаю Java, и напал на задачку, к которой никак не подберусь. Условие следующее:
Given an array of strings, reverse them and their order in such way that their length stays the same as the length of the original inputs. Example:
Input:
{"Don't", "worry", ",", "be", "happy", "!"}Output:
{"!yppa", "heb,y", "r", "ro", "wt'no", "D"}
Моя вариация решения:
public class ArrayReverser {
public static String[] reverse(String[] a) {
for (int j = 0; j < a.length; j++) {
char[] charArray = a[j].toCharArray();
String resultString = "";
for (int i = charArray.length - 1; i >= 0; i--) {
resultString += charArray[i];
}
a[j] = resultString;
}
return a;
}
}
Ошибка:
Result should be [!dneirf, ym, ,ava, J, ot, emocle, W]
for input [Welcome, to, Java, ,, my, friend, !]
: arrays first differed at element [0]; expected:<[!dneirf]> but was:<[emocleW]>
at org.junit.internal.ComparisonCriteria.arrayEquals(ComparisonCriteria.java:78)
at org.junit.internal.ComparisonCriteria.arrayEquals(ComparisonCriteria.java:28)
at org.junit.Assert.internalArrayEquals(Assert.java:534)
at org.junit.Assert.assertArrayEquals(Assert.java:285)
at ArrayReverserTest.arrayReverser_positiveTest(ArrayReverserTest.java:12)
... 51 trimmed
Caused by: org.junit.ComparisonFailure: expected:<[!dneirf]> but was:<[emocleW]>
at org.junit.Assert.assertEquals(Assert.java:117)
at org.junit.Assert.assertEquals(Assert.java:146)
at org.junit.internal.ExactComparisonCriteria.assertElementsEqual(ExactComparisonCriteria.java:8)
at org.junit.internal.ComparisonCriteria.arrayEquals(ComparisonCriteria.java:76)
... 56 more
Ответы (3 шт):
Ты переворачиваешь каждое слово, а надо всю строку. Пройди по входному массиву строк, сохраняя длину каждого слова в отдельный интовый массив длин, превращая строки в массивы char и складывая их подряд в единый массив char.
Потом бери с конца единого массива количество char, соответствующее длине первого слова из массива длин и по одному символу пиши в строку, эту строку пиши в результирующий массив строк.
Можно сразу формировать единый массив char, записывая в перевернутые слова в него.
Еще можно брать длину первого слова и отсчитывать с конца для него буквы, но так сложнее писать и легче ошибиться, надо учитывать длину слов в конце массива строк и брать необходимое количество. С единым массивом char проще.
Или так можно:
String[] in = {"Welcome", "to", "the", "Moon", "!"};
int arrLength = in.length;
StringBuilder sb = new StringBuilder();
int[] count = new int[arrLength];
int i = 0;
for (String s: in) {
sb.append(s); //"WelcometotheMoon!"
count[i]=s.length(); // 7, 2, 3, 4, 1
i++;
}
sb.reverse(); //"!nooMehtotemocleW"
String[] res = new String[arrLength];
int start = 0;
for (int j = 0; j < arrLength; j++) {
res[j] = sb.substring(start, start + count[j]);
start += count[j];
System.out.print(res[j] + " "); // "!nooMeh" "to" "tem" "ocle" "W"
}
}
Если в лоб, то можно так:
public static String[] reverse(String[] inputArr) {
return Stream.of(inputArr)
.collect(StringBuilder::new, (sb, s) -> sb.append(s).append(" "), StringBuilder::append)
.reverse().toString().trim().split(" ");
}
String[] inputArr = {"Don't", "worry", ",", "be", "happy", "!"};
String[] resultArr = new String[inputArr.length];
Character[] chars = Stream.of(inputArr)
.flatMapToInt(CharSequence::chars)
.mapToObj(i -> (char) i)
.toArray(Character[]::new);
int pos = chars.length - 1;
for (int j = 0; j < inputArr.length; j++) {
String s = inputArr[j];
resultArr[j] = "";
for (int i = 0; i < s.length(); i++) {
resultArr[j] += chars[pos--];
}
}
// output: [!yppa, heb,y, r, ro, wt'no, D]
System.out.println(Arrays.toString(resultArr));