Сопряжение повторяющихся элементов в массиве

#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. Спасибо тебе, Вым. Я действительно ценю это. Довольно новичок здесь, привыкаю к этому.