#ios #arrays #swift #xcode #loops
Вопрос:
Я пытаюсь соединить повторяющиеся элементы массива и подсчитать пары.
Когда заданный массив является : [10, 20, 20, 10, 10, 30, 50, 10, 20], Я ожидаю, что количество пар будет 3. Потому что есть 2 пары по 10 и 1 пара по 20.
Мое «условие if» проверяет, является ли индекс текущего элемента первым индексом или нет. Если это не последний индекс, это означает, что существует дубликат текущего элемента. Поэтому я добавляю 1 к числу пар.
Для ввода [10, 20, 20, 10, 10, 30, 50, 10, 20], мое количество пар равно 2, но должно быть 3. Для ввода [1 1 3 1 2 1 3 3 3 3], myNumberOfPairs вообще не печатает? Но вместо этого должно быть 4.
Боже, чего мне здесь не хватает?
func sockMerchant(n: Int, ar: [Int]) -> Int {
// Write your code here
var array = ar
var numberOfPairs = 0
for i in 0..<array.count {
var element = array[i]
let indexOfLastElement = array.lastIndex(of: element)
let indexOfFirstElement = array.firstIndex(of: element)
print("indexOfLastElement is (indexOfLastElement)")
print("indexOfFirstElement is (indexOfFirstElement)")
if indexOfFirstElement != indexOfLastElement {
numberOfPairs = 1
array.remove(at: indexOfFirstElement!)
array.remove(at: indexOfLastElement!)
continue
}
return numberOfPairs
}
return numberOfPairs
}
Комментарии:
1. Это довольно просто: начните с простого примера и отладьте свою программу. Одношаговый просмотр кода, проверка переменных. В какой момент программа ведет себя не так, как вы думали?
Ответ №1:
Я согласен с @MartinR в том, что в таких случаях вам следует размещать точки останова и просматривать свой код строка за строкой, радуясь, что вы сами обнаружили свою ошибку.
Но также и с точки зрения производительности, lastIndex
и firstIndex
это очень тяжелые операции, потому что они могут пройти все элементы и ничего не найти, что делает большую запись вашего алгоритма O вокруг O(log n). В таких случаях широко используется словарь(если вы не сильно ограничены пространством).
Вы можете использовать значение как a key
и считать как a value
для словаря и подсчитать все элементы, а затем просто суммировать следующим образом:
func sockMerchant(ar: [Int]) -> Int {
ar.reduce(into: [Int:Int]()) { map, value in
map[value, default: 0] = 1
}.reduce(0) { sum, count in
sum count.value / 2
}
}
Комментарии:
1. Это не возвращает правильный результат. Пожалуйста, проверьте с помощью примеров в вопросе или простого тестового примера, [1,1,1,1]
2. @JoakimDanielson Спасибо, я немного неправильно понял вопрос, обновленный ответ должен сработать
3. Swift-это язык, определяемый типом
reduce(into: [:]) { $0[$1, default: 0] = 1 }.reduce(0) { $0 $1.value/2 }
4. @LeoDabus, конечно, ты можешь это сделать. Но я думаю, что название аргументов значительно улучшает читабельность; Я использую стенографию только тогда, когда вычисления довольно просты. То же самое касается типов словарей: я хотел бы, чтобы автор был более ясен в том, что здесь происходит. Кроме того, swift может очень плохо показывать ошибки и давать предложения в коде
[:]
.5. Что на самом деле делает карта[значение по умолчанию :0] = 1?
Ответ №2:
Вы мутируете свой array
, звоня remove(at:)
одновременно с доступом к нему, вот почему у вас возникают эти странные побочные эффекты.
Я предполагаю, что вы пытаетесь решить задачу с литкодом (или что-то подобное), поэтому я не буду предлагать решение заранее. Я предлагаю вам подумать об алгоритме, который не предполагает изменения содержимого Списка, пока вы читаете содержимое этого же списка.
Ответ №3:
Итак, я решил проблему, как показано ниже, благодаря @Vym и @Martin R.
func sockMerchant(n: Int, ar: [Int]) -> Int {
// Write your code here
var array = ar
var numberOfPairs = 0
var newArray = [Int]()
var done = false
for i in 0..<array.count {
let element = array[i]
let indexOfLastElement = array.lastIndex(of: element)
let indexOfFirstElement = array.firstIndex(of: element)
if indexOfFirstElement != indexOfLastElement {
newArray.append(element)
numberOfPairs = newArray.count/2
done = true
}
}
if done == true {
return numberOfPairs
}
return numberOfPairs
}
Комментарии:
1. Рад, что вы смогли прийти к рабочему решению. P.S. Я лично не обвинял вас в каком-либо мошенничестве. Пожалуйста, в следующий раз избегайте использования всех заглавных букв и имейте в виду, что это веб-сайт вопросов и ответов, где ответы, основанные на мнениях, не приветствуются.
2. Не беспокойтесь! Нисходящий голос есть нисходящий голос — не переживайте из-за этого. Тебе не нужно ничего объяснять.
3. Спасибо тебе, Вым. Я действительно ценю это. Довольно новичок здесь, привыкаю к этому.