Модификация массива в Python на месте - PullRequest
0 голосов
/ 15 сентября 2018

Я обнаружил, что этот вопрос требует модификации массива на месте, чтобы все нули перемещались в конец массива и сохранялся оставшийся порядок ненулевых элементов.На месте, согласно постановке задачи, означает не делать копию исходного массива.(Это взято из Leetcode и может быть найдено как # 283, Move Zeroes)

Пример ввода и вывода будет, [0,1,0,13,12] становится [1,13,12,0,0].Я нашел одно простое решение:

for num in nums:
    if num == 0:
        nums.remove(num)
        nums.append(0)

Решение ясное и простое в применении, поэтому я понял, что оно делает то, что должно.

Однако я не до конца понимаю / продан на месте, потому что я не уверен, как удаление работает в фоновом режиме.Делает ли внутреннее удаление копию массива для удаления указанного элемента - как это работает?Используя это понятие «на месте», считается ли мое первоначальное решение ниже на месте (поскольку оно не делает никаких копий чисел, а скорее изменяет исходную версию чисел)?

indices = []
for en, num in enumerate(nums): # get the index of all elements that are 0
    if num == 0:
        indices.append(en)

for en, i in enumerate(indices): 
    new_i = i-en # use the index, accounting for the change in length of the array from removing zeros
    nums = nums[:new_i] + nums[new_i+1:] # remove the zero element
nums = nums + [0] * len(indices) # add back the appropriate number of zeros at the end

1 Ответ

0 голосов
/ 15 сентября 2018

Удаляет ли внутренне удаление копию массива для удаления указанного элемента?

Нет

Как это работает?

Из исходного кода python для списков , remove() вызывает listremove():

listremove(PyListObject *self, PyObject *v)
{
    Py_ssize_t i;

    for (i = 0; i < Py_SIZE(self); i++) {
        int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);
        if (cmp > 0) {
            if (list_ass_slice(self, i, i+1, (PyObject *)NULL) == 0)
                Py_RETURN_NONE;
            return NULL;
        }
        else if (cmp < 0)
            return NULL;
    }
    PyErr_SetString(PyExc_ValueError, "list.remove(x): x not in list");
    return NULL;
}

Python разбивает список по индексу элемента, который необходимо удалить.Я нашел лучшее описание функции удаления здесь :

arguments: list object, element to remove
returns none if OK, null if not
listremove:
    loop through each list element:
        if correct element:
            slice list between element's slot and element's slot + 1
            return none
    return null

enter image description here

С вашим понятием "на месте"Я бы сказал, что это справедливо и работает для вашей конкретной ситуации.Но кто-то уже высказал свое мнение о том, чтобы не вносить изменения в список во время его итерации.

...