Некоторые замечания по вашему коду:
- Вы смотрите только на первый (0-й) элемент и никогда не увеличиваете
i
, поэтому вы не проверяете ни один из последующих элементов на предмет дублирования. - Аргумент
length
является избыточным, поскольку мы можем определить длину Array
, s
через его атрибут .length
(или .size
).Использование атрибута .length
безопаснее, поскольку оно всегда допустимо.Например, duplicate(Array(1, 2, 3, 4, 5, 3), 10)
вызывает исключение (java.lang.ArrayIndexOutOfBoundsException
), поскольку массив не имеет 10 членов. - Вы инициализируете
j
, чтобы иметь то же значение, что и i
, а затем сравниваете s(i) == s(j)
, поэтому вы всегда будете получать дубликаты на первом элементе, даже если в массиве нет дублирования. - Вы возвращаете
result
(что указывает на то, нашли ли вы результат), скореечем isDupli
(который указывает, нашли ли вы дубликат).К счастью, нам нужен только один из них, поскольку поиск результата аналогичен поиску дубликата.
Вот еще одна версия, которая устраняет эти проблемы и упрощает некоторый код:
def duplicate(s: Array[Int]): Boolean = {
val length = s.length
var i = 0 // start counting at value 0
var foundDuplicate = false // Type inference means Scala knows this is Boolean
// Loop through each member until we've found a duplicate.
//
// Note that "!foundDuplicate" is the same as "foundDuplicate == false"
while(i < length && !foundDuplicate) {
// Now compare to each of the remaining elements. Start at the element above i.
var j = i + 1
// Loop through each of the remaining elements.
while(j < length && !foundDuplicate) {
// If we find a match, we're done.
if (s(i) == s(j)) {
foundDuplicate = true
}
// Look at the next j
j += 1
}
// Look at the next i
i += 1
}
// Return the result. If we didn't find anything, this will still be false.
foundDuplicate
}
val myArray1 = Array(1, 2, 3, 4, 5, 6, 2, 8, 9)
val myArray2 = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
duplicate(myArray1) // Returns true
duplicate(myArray2) // Returns false
Однако, хотя это совершенно нормально процедурный код, в Scala мы можем использовать гораздо лучший функциональный стиль.(В процедурном коде используются var
s, while
циклы и т. Д., Которые не одобряются в Scala .)
import scala.annotation.tailrec
def duplicate(s: Array[Int]): Boolean = {
// Helper function to search the array for matches to element at i
@tailrec // Indicates function is tail recursive.
def matchElement(i: Int): Boolean = {
// Helper function to search for a match in remainder of array.
@tailrec
def matchRem(j: Int): Boolean = {
// If j has reached the end of the array, we had no match.
if(j >= s.length) false
// Otherwise, does this element match the target? Match found.
else if (s(i) == s(j)) true
// Otherwise, look at the next element after j.
else matchRem(j + 1) // Recursive call
}
// If this is the last character of the array, then we can't have a match.
if(i >= s.length - 1) false
// Otherwise did we find a duplicate in the remainder of this array?
else if(matchRem(i + 1)) true
// Otherwise, perform another iteration looking at the next element.
else matchElement(i + 1) // Recursive call
}
// Start the ball rolling by looking at for duplicates of the first character.
matchElement(0)
}
Это может показаться довольно сложным, на первый взгляд, нообратите внимание, что он не имеет любых var
объявлений или while
циклов.Конечно, это решение roll-your-own .Существуют гораздо более простые методы достижения этого с использованием других Array
функций.