Как поместить массив в обратном порядке? [dубликат]

Я пытаюсь изменить массив int в Java.

Этот метод не отменяет массив.

for(int i = 0; i < validData.length; i++)
{
    int temp = validData[i];
    validData[i] = validData[validData.length - i - 1];
    validData[validData.length - i - 1] = temp;
}

Что с ним не так?

190
задан 9 May 2018 в 00:45

29 ответов

Если вы работаете с более примитивными данными (т. е. char, byte, int и т. д.), вы можете делать некоторые интересные операции XOR.

public static void reverseArray4(int[] array) {
    int len = array.length;
    for (int i = 0; i < len/2; i++) {
        array[i] = array[i] ^ array[len - i  - 1];
        array[len - i  - 1] = array[i] ^ array[len - i  - 1];
        array[i] = array[i] ^ array[len - i  - 1];
    }
}
4
ответ дан 15 August 2018 в 15:36
  • 1
    Слишком мило, чтобы на самом деле использовать в производственном коде, но, тем не менее, весело. Для максимальной гибкости используйте операцию% = следующим образом: array [i]% = array [len - i - 1] и т. Д. – Melinda Green 12 February 2015 в 06:17
  • 2
    Похоже, но немного короче: for (int m = x.length, i = --m / 2; ++i <= m;) { x[i] ^= x[m - i]; x[i] ^= x[m - i] ^= x[i]; } – Thomas Mueller 30 June 2016 в 11:07
[F1]
2
ответ дан 15 August 2018 в 15:36

Вот как я лично ее разрешу. Причина создания параметризованного метода заключается в том, чтобы разрешить сортировку любого массива ... не только ваши целые числа.

Надеюсь, вы что-то извлекли из него.

@Test
public void reverseTest(){
    Integer[] ints = {1, 2, 3, 4};
    Integer[] reversedInts = reverse(ints);
    assertEquals(Integer.valueOf(1), reversedInts[3]);
    assertEquals(Integer.valueOf(4), reversedInts[0]);
}

public static <T> T[] reverse(T[] arrayToReverse){
   //as per the collections spec (and pointed out by @Radiodef)
   // the collections api will sort the array in place.
   Collections.reverse(Arrays.asList(arrayToReverse));
   return arrayToReverse;
}
4
ответ дан 15 August 2018 в 15:36
  • 1
    Не решает исходную проблему с использованием примитивов. – Melinda Green 12 February 2015 в 06:19
  • 2
    Существует много способов преобразования примитивов в объекты. Я всегда рекомендую избегать приемов, где это возможно, в java, и я также считаю, что его следует поощрять. – AnthonyJClink 12 February 2015 в 22:04
  • 3
    Преобразование массива примитивов неизвестной длины в массив может быть очень плохой идеей, особенно если это сделано без ее реализации. Java не Smalltalk. Примитивы являются частью языка и имеют свое место. Не имеет значения, не нравимся ли они им, мы должны их принять и использовать там, где это необходимо. – Melinda Green 13 February 2015 в 04:33
  • 4
    Вам не нужно копировать массив, просто Collections.reverse(asList(arraytoReverse)); return arrayToReverse;. asList - это просто оболочка вокруг массива, поэтому исходный массив обратный. – Radiodef 12 June 2015 в 06:03
[F1]
0
ответ дан 15 August 2018 в 15:36

Я думаю, что немного легче следовать логике алгоритма, если вы объявляете явные переменные для отслеживания индексов, которые вы обмениваете на каждой итерации цикла.

public static void reverse(int[] data) {
    for (int left = 0, right = data.length - 1; left < right; left++, right--) {
        // swap the values at the left and right indices
        int temp = data[left];
        data[left]  = data[right];
        data[right] = temp;
    }
}

Я также думаю, что это более читаемо для этого в цикле while.

public static void reverse(int[] data) {
    int left = 0;
    int right = data.length - 1;

    while( left < right ) {
        // swap the values at the left and right indices
        int temp = data[left];
        data[left] = data[right];
        data[right] = temp;

        // move the left and right index pointers in toward the center
        left++;
        right--;
    }
}
37
ответ дан 15 August 2018 в 15:36
  • 1
    старая школьная свопа выглядит более просто, но да, когда значения индекса массива left, right, ... будут полезны для отладки, если они есть – Srinath Ganesh 25 July 2014 в 06:34
  • 2
    Вы также можете добавить 'public static void swap (int [] data, int index1, int index2) {...}' и использовать это из 'reverse' следующим образом: swap (data, left, right). – pm_ 10 December 2015 в 19:29

Вот простая реализация, обратная матрица любого типа плюс полная / частичная поддержка.

import java.util.logging.Logger;

public final class ArrayReverser {
 private static final Logger LOGGER = Logger.getLogger(ArrayReverser.class.getName());

 private ArrayReverser () {

 }

 public static <T> void reverse(T[] seed) {
    reverse(seed, 0, seed.length);
 }

 public static <T> void reverse(T[] seed, int startIndexInclusive, int endIndexExclusive) {
    if (seed == null || seed.length == 0) {
        LOGGER.warning("Nothing to rotate");
    }
    int start = startIndexInclusive < 0 ? 0 : startIndexInclusive;
    int end = Math.min(seed.length, endIndexExclusive) - 1;
    while (start < end) {
        swap(seed, start, end);
        start++;
        end--;
    }
}

 private static <T> void swap(T[] seed, int start, int end) {
    T temp =  seed[start];
    seed[start] = seed[end];
    seed[end] = temp;
 }  

}

Вот соответствующий модульный тест

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import org.junit.Before;
import org.junit.Test;

public class ArrayReverserTest {
private Integer[] seed;

@Before
public void doBeforeEachTestCase() {
    this.seed = new Integer[]{1,2,3,4,5,6,7,8};
}

@Test
public void wholeArrayReverse() {
    ArrayReverser.<Integer>reverse(seed);
    assertThat(seed[0], is(8));
}

 @Test
 public void partialArrayReverse() {
    ArrayReverser.<Integer>reverse(seed, 1, 5);
    assertThat(seed[1], is(5));
 }
}
0
ответ дан 15 August 2018 в 15:36
[F1]
4
ответ дан 15 August 2018 в 15:36
  • 1
    К сожалению, это самый чистый ответ, доступный здесь, потому что каждый разработчик будет знать, как это сделать, и он не требует каких-либо расширенных пакетов. – HoldOffHunger 16 June 2017 в 03:15
Collections.reverse(Arrays.asList(yourArray));

java.util.Collections.reverse() может отменить java.util.List s, а java.util.Arrays.asList() возвращает список, который обертывает конкретный массив, который вы передаете ему, поэтому yourArray отменяется после вызова Collections.reverse().

Стоимость - это просто создание одного объекта List и никаких дополнительных библиотек не требуется.

Аналогичное решение было представлено в ответе Тарика и их комментаторов, но я думаю, что этот ответ будет быть более кратким и более легко разбираемым.

25
ответ дан 15 August 2018 в 15:36
  • 1
    Для массивов объектов это хорошее решение. Но он не работает для массивов примитивов. E. g. передача int[] в asList(...) не вернет List<Integer>, а List<int[]>, содержащий один элемент. В AFAICS нет простого встроенного способа преобразования int[] в Integer[]. – Martin Rust 22 September 2016 в 10:14
  • 2
    Это не работает с примитивными массивами ... коллекции не возвращают значение, поэтому теперь у вас есть бесполезный массив в виде списка в памяти – NightSkyCode 23 October 2016 в 23:08

Ваша программа будет работать только для length = 0, 1. Вы можете попробовать:

int i = 0, j = validData.length-1 ; 
while(i < j)
{
     swap(validData, i++, j--);  // code for swap not shown, but easy enough
}
2
ответ дан 15 August 2018 в 15:36
  • 1
    Возможно, вы использовали swap как псевдокод для встроенного свопа, а не для вызова метода, но если это не сработает. Java проходит по ссылке, поэтому невозможно написать метод подкачки для переменных. – Dean Povey 26 January 2010 в 11:27
  • 2
    Я имел в виду, каким образом вы можете получить v [i] & amp; v [j] для обмена. Я знаю, как вызовы методов работают в java. Для метода вы можете сделать что-то вроде swap (v, i ++, j--); – fastcodejava 26 January 2010 в 11:39
  • 3
    Дин, массив validData - это объект, переданный по ссылке, поэтому метод swap () будет работать отлично. – Gaël Oberson 21 August 2015 в 14:37

Это работает, если вы хотите вернуться, пока не дойдете до середины массива?

    double [] list = {11,21,31,41,51,61,71,81,91};
    int midpoint = list.length/2 -1;
    int firstVal = 0;
    while(firstVal < midpoint){
        double midPoint = list[midpoint];
        double firstValue = list[firstVal];
        list[midpoint] = firstValue;
        list[firstVal] = midPoint;

        firstVal = firstVal + 1;
        midpoint = midpoint-1;
    }
    StdOut.println(Arrays.toString(list));
}
0
ответ дан 15 August 2018 в 15:36

Вот простое быстрое решение. Надеюсь, это поможет!

public int[] reverse(int[] arr) {
    for(int i = arr.length; i > 0 ; i--){
        System.out.print(arr[i-1] + " ");
    }
    return arr;
}
2
ответ дан 15 August 2018 в 15:36
  • 1
    Он не будет возвращать массив как обратный! – InziKhan 8 June 2018 в 22:58

В случае Java 8 мы также можем использовать потоки для обращения к целочисленному массиву как:

int[] sample = new int[]{1,2,3,4,5};
int size = sample.length;
int[] reverseSample = IntStream.range(0,size).map(i -> sample[size-i-1])
                      .toArray(); //Output: [5, 4, 3, 2, 1]
1
ответ дан 15 August 2018 в 15:36

С Commons.Lang вы могли бы просто использовать

ArrayUtils.reverse(int[] array)

. В большинстве случаев быстрее и безопаснее использовать легкодоступные библиотеки, которые уже тестировались и тестировались пользователем, когда они позаботьтесь о своей проблеме.

273
ответ дан 15 August 2018 в 15:36
  • 1
    Я бы предпочел, чтобы он вернул реверсивный (прошедший) массив для функционального стиля. – Laurent G 2 October 2017 в 15:19
  • 2
    @ laurent-g, чтобы быть справедливым: для обратного массива этот способ более эффективен с точки зрения памяти, и, вероятно, поэтому они сделали это таким образом. – Sirmyself 13 April 2018 в 23:32
  • 3
    Моя точка зрения не была копией или не копией. «Мои сообщения» («пройдены») (после обращения вспять), поэтому он может быть передан в выражении, не требующем отдельного утверждения. – Laurent G 17 April 2018 в 09:47

Другой способ обращения к массиву

public static int []reversing(int[] array){
    int arraysize = array.length;
    int[] reverse = new int [arraysize+1];
    for(int i=1; i <= arraysize ; i++){
        int dec= arraysize -i;
        reverse[i] = array[dec];
    }
    return reverse;
}
0
ответ дан 15 August 2018 в 15:36

Поскольку я намеревался сохранить свой первоначальный массив, я решил эту проблему следующим образом:

List<Integer> normalArray= new ArrayList<>();
List<Integer> reversedArray = new ArrayList<>();

// Fill up array here

for (int i = 1; i <= normalArray.size(); i++) {
  reversedArray .add(normalArray.get(normalArray.size()-i));
}

Итак, в основном, цикл через начальный массив и добавьте все значения в обратном порядке, чтобы новый (обратный) массив. Тип списка может быть любым. Я много раз работаю над этим кодом, поэтому некоторые другие решения не работают.

0
ответ дан 15 August 2018 в 15:36

ниже - полная программа для запуска на вашем компьютере.

public class ReverseArray {
    public static void main(String[] args) {
        int arr[] = new int[] { 10,20,30,50,70 };
        System.out.println("reversing an array:");
        for(int i = 0; i < arr.length / 2; i++){
            int temp = arr[i];
            arr[i] = arr[arr.length - i - 1];
            arr[arr.length - i - 1] = temp;
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }   
    }
}

Для программ на матрице с использованием массивов это будет хороший источник. По ссылке.

0
ответ дан 15 August 2018 в 15:36

Не будет ли это делать так мало вероятным для ошибок?

    int[] intArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int[] temp = new int[intArray.length];
    for(int i = intArray.length - 1; i > -1; i --){
            temp[intArray.length - i -1] = intArray[i];
    }
    intArray = temp;
0
ответ дан 15 August 2018 в 15:36

Лучше всего просто перебрать массив назад.

Я не уверен, что решение Aaron делает это vi этим вызовом Collections.reverse(list); Кто-нибудь знает?

3
ответ дан 15 August 2018 в 15:36
  • 1
    Итерация назад по массиву требует нового массива. Мне нравится решение, опубликованное выше, которое делает встроенное реверсирование без создания нового массива. – mmcdole 26 January 2010 в 10:27
  • 2
    Коллекции не работают с массивами. – phreakhead 28 October 2016 в 02:31

Здесь уже много ответов, в основном сосредоточено на изменении массива на месте. Но для полноты, вот еще один подход с использованием потоков Java для сохранения исходного массива и создания нового реверсивного массива:

    int[] a = {8, 6, 7, 5, 3, 0, 9};
    int[] b = IntStream.rangeClosed(1, a.length).map(i -> a[a.length-i]).toArray();
7
ответ дан 15 August 2018 в 15:36
[F1]
5
ответ дан 15 August 2018 в 15:36
  • 1
    Пожалуйста, подумайте над тем, чтобы добавить объяснение к вашему ответу. Ответы только на код ничего не объясняют. – rgettman 10 December 2014 в 00:05

Попробуйте этот код:

    int arr[] = new int[]{1,2,3,4,5,6,7};
    for(int i=0;i<arr.length/2;i++){
        int temp = arr[i];
        arr[i] = arr[(arr.length-1)-i];
        arr[(arr.length-1)-i] = temp;
     }
     System.out.println(Arrays.toString(arr));
0
ответ дан 15 August 2018 в 15:36

Простой для цикла!

for (int start = 0, end = array.length - 1; start <= end; start++, end--) {
    int aux = array[start];
    array[start]=array[end];
    array[end]=aux;
}
5
ответ дан 15 August 2018 в 15:36
  • 1
    В будущем, пожалуйста, позвольте ассеру узнать, что именно они сделали неправильно, и что вы сделали правильно. – K_7 5 February 2017 в 21:55
[F1]
2
ответ дан 15 August 2018 в 15:36

Решение с o (n) временной сложностью и o (1) сложностью пространства.

void reverse(int[] array) {
    int start = 0;
    int end = array.length - 1;
    while (start < end) {
        int temp = array[start];
        array[start] = array[end];
        array[end] = temp;
        start++;
        end--;
    }
}
0
ответ дан 15 August 2018 в 15:36
  • 1
    Просто FYI, это может быть упрощено в комплекс для цикла: for (int start = 0, end = array.length - 1; start < end; start++, end--) { ... }. – Tim Cooke 25 October 2017 в 08:34

Используя решение XOR, чтобы избежать временной переменной, ваш код должен выглядеть так:

for(int i = 0; i < validData.length; i++){
    validData[i] = validData[i] ^ validData[validData.length - i - 1];
    validData[validData.length - i - 1] = validData[i] ^ validData[validData.length - i - 1];
    validData[i] = validData[i] ^ validData[validData.length - i - 1];
}

См. эту ссылку для лучшего объяснения:

http://betterexplained.com/ статьи / своп-две переменных-используя-исключающий /

0
ответ дан 15 August 2018 в 15:36
[F1]
41
ответ дан 15 August 2018 в 15:36
  • 1
    Массив из ints не объектов, это не сработает. – Tom 26 January 2010 в 10:24
  • 2
    Конечно, будет. Список может содержать только объекты, а не примитивы, поэтому все примитивы (int s в этом случае) помещаются в соответствующие оболочки (Integer s в этом случае) и помещаются в список. Вы видите, Integer s - объекты. @Том – 11684 3 December 2012 в 23:03
  • 3
    Остерегайтесь: если я не ошибаюсь, исходный массив изменяется. Чтобы было ясно, вы можете просто ничего не возвращать. – Andrea Zilio 6 February 2013 в 01:25
  • 4
    как бы вы преобразовали массив Object [], который возвращается обратно в массив int [] ??? OP задал вопрос для массива ints, поэтому не могли бы вы дать код, который работает для массива ints из коробки? Благодарю. – vincent mathew 20 May 2013 в 10:30
  • 5
    @Andrea На самом деле, это не так. Список, возвращенный Arrays.asList(), не ссылается на исходный массив, и массив не возвращается. Это одна из проблем с этим методом: он использует тройную память и выполняет тройную работу как алгоритм на месте. – Brian McCutchon 18 October 2014 в 21:25
[F1]
1
ответ дан 15 August 2018 в 15:36

С Guava:

Collections.reverse(Ints.asList(array));
7
ответ дан 15 August 2018 в 15:36
  • 1
    Это великолепно! Короткие и эффективные. Как и все asList методы, он создает представление , которое записывается непосредственно в массив основы (примитивного). Я думаю, что нисходящий избиратель здесь ошибочно думал, что это вернуло список в коробке или что-то в этом роде. – Luke Usherwood 29 December 2016 в 13:33
  • 2
    В самом деле, об этом стоит знать. Я не думаю, что это было бы большой проблемой в большинстве кодов, с которыми я лично работаю - наши «горячие» области хорошо определены, остальное - «код клея». В то же время я убежден в том, что отторжение памяти также создает дополнительный «скрытый» стоимость, которую профилировщики не приписывают фактической функции. – Luke Usherwood 13 February 2017 в 17:35

Это поможет вам

int a[] = {1,2,3,4,5};
for (int k = 0; k < a.length/2; k++) {
    int temp = a[k];
    a[k] = a[a.length-(1+k)];
    a[a.length-(1+k)] = temp;
}
5
ответ дан 15 August 2018 в 15:36

Другие вопросы по тегам:

Похожие вопросы: