Здесь существуют некоторые большие, эффективные решения. Однако для любого не обеспокоенного абсолютом, самым эффективным O(n)
решение, я пошел бы с простой остротой O(n^2*log(n))
решение:
def unique(xs):
return sorted(set(xs), key=lambda x: xs.index(x))
или более эффективный с двумя лайнерами O(n*log(n))
решение:
def unique(xs):
positions = dict((e,pos) for pos,e in reversed(list(enumerate(xs))))
return sorted(set(xs), key=lambda x: positions[x])
В Java все вычисления выполняются в самом большом типе данных, необходимом для обработки всех текущих значений. Итак, если у вас int * int, математика всегда будет выполняться как целое число, но int * long - как long.
В этом случае 1024 * 1024 * 1024 * 80 выполняется как Int, который переполняет int.
"L", конечно, заставляет один из операндов быть Int-64 (long), поэтому вся математика выполняется с сохранением значений как Long, поэтому переполнения не происходит.
Целочисленные литералы - это int
s. Переполнение int
. Используйте суффикс L
.
long value = 1024L * 1024L * 1024L * 80L;
Если данные поступили из переменных, которые либо преобразуются, либо заранее присваиваются значениям long.
long value = (long)a * (long)b;
long aL = a;
long bL = b;
long value = aL*bL
Строго говоря, вы можете обойтись меньшим количеством значений, но, вероятно, лучше прояснить ситуацию.
Также не строчные буквы l
в качестве суффикса можно спутать с 1
.
Я подозреваю, что это потому, что по умолчанию java обрабатывает литералы как целые числа, а не как длинные. Итак, без L на 80 умножение переполняется.
Этот код:
long value = 1024 * 1024 * 1024 * 80;
умножает некоторые целые числа, преобразует их в длинное и затем присваивает результат переменной. Фактическое умножение будет выполняться javac, а не при его запуске.
Так как int 32 бита, значение переносится в оболочку и приводит к нулю.
Как вы говорите, использование длинных значений в правой части даст результат, который переносится, только если оно превышает 64 бита.