#java #arrays #sorting #arraylist
#java #массивы #сортировка #список массивов
Вопрос:
Существует два массива int и список массивов под названием costs и shipping . Мне нужен ArrayList, который имеет наименьшую или наибольшую общую цену (например, стоимость [0] доставка [0]), но измените порядок двух массивов int в соответствии с ArrayList:
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int[] costs = new int[n];
int[] shipping = new int[n];
ArrayList<Integer> totalCosts = new ArrayList<>();
Например, предположим, что затраты равны [1, 5, 2, 3], а доставка равна [2, 3, 2, 4], таким образом, totalCosts будет равен {3, 8, 4, 7} и будет отсортирован по {3, 4, 7, 8}. Я хочу, чтобы затраты и доставка были переупорядочены таким образом, чтобы они соответствовали итоговым значениям, поэтому затраты были бы [1, 2, 3, 5], а доставка была бы [2, 2, 4, 3].
Комментарии:
1. вы хотите этого и что вы пытались для этого сделать?
2. Это очень сложно сделать, так как вам нужно будет перемещать элементы массива в зависимости от того, как элементы списка перемещались при сортировке. Проще создать новый класс, который содержит затраты, доставку и общую цену. Затем составьте список из них и отсортируйте его.
3. Как правило, наличие нескольких коллекций, которые должны поддерживаться параллельно, является плохой идеей . Я бы создал
List<Order>
, где класс Order имеет 2 поля, стоимость и доставка, и методgetTotal
, который их суммирует. Затем сортировка становится тривиальнойList.sort
, и поскольку данные логически группируются в объекты, индексы поддерживаются автоматически. Вы можете снова разбить это на новые массивы, если вам действительно нужно4. Использование HashMap здесь может быть еще лучше, а затем просто вызвать sort на вашей карте, поскольку сортировка по умолчанию стабильна, проблем быть не должно!
Ответ №1:
Вот решение, которое не использует карту. Вместо этого у нас есть пользовательский компаратор, который использует сумму затрат и доставки для сортировки позиций массива. Затем мы создаем новые массивы и выбираем значения из отсортированных позиций в старых массивах.
public static void main(String[] args) {
int n = 4;
int[] costs = {1, 5, 2, 3};
int[] shipping = {2, 3, 2, 4};
Integer[] totals = new Integer[n];
for(int i = 0; i < n; i) {
totals[i] = i;
}
Arrays.sort(totals, Comparator.comparingInt(k -> (costs[k] shipping[k])));
int[] newCosts = new int[n];
int[] newShipping = new int[n];
for(int i = 0; i < n; i) {
newCosts[i] = costs[totals[i]];
newShipping[i] = shipping[totals[i]];
}
for(int i = 0; i < n; i){
System.out.println((i 1) ": Cost=" newCosts[i] ", Shipping=" newShipping[i] ", Total=" (newCosts[i] newShipping[i]));
}
}
Объяснение
Массив итогов содержит список индексов от 0 до n (4 в примере). Arrays.sort()
сортирует индекс с помощью компаратора, который, учитывая индекс, извлекает итоговые данные для этой позиции. В массиве итогов после сортировки будет указан индекс сумм стоимости и доставки по порядку.
После этого мы можем создать новые массивы затрат и доставки, используя отсортированные индексы.
Редактировать
Следуя совету ttzn из комментариев, вы можете сжать код до этого:
public static void main(String[] args) {
int n = 4;
int[] costs = {1, 5, 2, 3};
int[] shipping = {2, 3, 2, 4};
int[] totals = IntStream.range(0, n).boxed().sorted(Comparator.comparingInt(k -> (costs[(int)k] shipping[(int)k]))).mapToInt(Integer::intValue).toArray();
int[] newCosts = IntStream.of(totals).map(i -> costs[i]).toArray();
int[] newShipping = IntStream.of(totals).map(i -> shipping[i]).toArray();
for (int i = 0; i < n; i) {
System.out.println((i 1) ": Cost=" newCosts[i] ", Shipping=" newShipping[i] ", Total=" (newCosts[i] newShipping[i]));
}
}
Комментарии:
1. Поскольку вы собираетесь использовать Java 8
comparingInt
, вы могли бы также пойтиint[] totals = IntStream.range(0, n)
иint[] newCosts = IntStream.of(totals).map(i -> costs[i]).toArray();
2. Хороший момент. Я согласен, что это лучший выбор, хотя это может быть сложнее понять, если вы не знакомы с потоками.
Ответ №2:
public List<Integer> sortPrices(int[] cost, int[] shipping) {
List<Integer> result = new ArrayList<>();
TreeMap<Integer, List<int[]>> map = new TreeMap<>();
int length = cost.length;
int[] origCost = new int[length];
int[] origShipping = new int[length];
for (int i = 0; i < length; i ) {
int price = cost[i] shipping[i];
int[] arr = {i, i};
map.putIfAbsent(price, new ArrayList<>());
map.get(price).add(arr);
origCost[i] = cost[i];
origShipping[i] = shipping[i];
}
int j = 0;
for (int price : map.keySet()) {
for (int[] arr : map.get(price)) {
int ci = arr[0];
int si = arr[1];
cost[j] = origCost[ci];
shipping[j] = origShipping[si];
j ;
result.add(price);
}
}
return resu<
}
Комментарии:
1. Вышеуказанное должно сработать. карта представляет собой древовидную карту с ключом, поскольку общая цена и значение представляют собой список массивов длиной 2. Список должен использоваться, поскольку у нас могут быть одинаковые общие цены более одного раза. Остальное, я полагаю, само объяснимо.
Ответ №3:
Я решил на python
просто поймите логику цикла, и тогда вы сможете это сделать.
for i in range(len(total)):
for j in range(len(total)):
if sorted_total[i]==total[j]:
new_costs[i]=costs[j]
new_shipping[i]=shipping[j]
print("i ",i)
print("j ",j)
break
Ответ №4:
Вот решение, основанное на потоке, без построения карты.
- A
Stream<int[]>
создается для хранения общего числа и индекса вint[]
массиве, - Поток сортируется с использованием пользовательского компаратора для этих массивов (сначала по сумме, затем по индексу)
- Намеренно используйте
peek
along withAtomicInteger
для изменения порядка вводаcosts
иships
массивов
Однако это может рассматриваться как «злоупотребление», усугубляемое побочным эффектом обновления данных вне потока - Создайте и верните массив итогов.
public static int[] getTotals(int[] costs, int[] ships) {
assert costs.length == ships.length;
int[] copyCosts = Arrays.copyOf(costs, costs.length);
int[] copyShips = Arrays.copyOf(ships, ships.length);
AtomicInteger ix = new AtomicInteger(0);
return IntStream.range(0, costs.length)
.mapToObj(i -> new int[]{ costs[i] ships[i], i })
.sorted(Comparator.<int[]>
comparingInt(p -> p[0])
.thenComparingInt(p -> p[1])
) // get sorted Stream<int[]>
.peek(p -> {
costs[ix.get()] = copyCosts[p[1]];
ships[ix.getAndIncrement()] = copyShips[p[1]];
})
.mapToInt(p -> p[0])
.toArray();
}