Подтвердить что ты не робот

Найдите второе наименьшее число в списке, используя рекурсию

Я знаю, что на этот вопрос был задан вопрос, но ни один из ответов не помог мне. Мне не нужна помощь в реализации кода, мне просто нужна помощь в сортировке через рекурсивный процесс для этого.

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

Как мне решить рекурсивный процесс для этой проблемы? Спасибо!

Изменить: Извините, что вы не указали достаточно подробностей, поэтому здесь идет.

Функция должна работать следующим образом:

>>> sm([1,3,2,1,3,2])
>>> 2

Второе редактирование: Извините за задержку, я был занят до сих пор, наконец, смог сесть и поставить то, что я имел в виду, в код. Он работает по назначению, но я честно считаю, что это очень дерьмовый и неэффективный способ сделать рекурсию, так как вы, вероятно, можете сказать, что я новичок в этой концепции.

Чтобы перефразировать мой оригинальный вопрос, используя псевдо-код ниже: возможно ли сделать то, что я здесь сделал, но не обертывая его второй функцией? То есть, возможно ли иметь функцию, которая только рекурсивно вызывает свое "я", и возвращает 1 номер - второе наименьшее число?

def second_smallest(list):
    def sm(list):
        if base case(len of list == 2):
            return ordered list [2nd smallest, smallest]
        else:
            *recursive call here*
            compare list[0] with returned ordered list
            eg: [3, [5,2]]
            re-arrange, and return a new ordered list
            [3,2]
    return sm(list)[0]
4b9b3361

Ответ 1

Вы можете написать свою рекурсивную функцию, чтобы принять 3 аргумента: первое и второе наименьшие значения, с которыми вы столкнулись до сих пор, и остальную часть списка, которую вы не проверяли.

Затем, сравнивая первый элемент аргумента списка с двумя наименьшими так далеко, вы можете выбрать, какой из 2 из 3 будет передан в качестве аргументов для следующей рекурсии.

Вам нужно обернуть эту рекурсивную функцию в функцию представления, которая устанавливает и вызывает рекурсивную, обрабатывая такие случаи, как списки с менее чем двумя элементами.

def recurse(min1, min2, list):
    if len(list)==0:
        return min2
    first, rest = list[0], list[1:]
    if first < min1:
        return recurse(first, min1, rest)
    if first < min2:
        return recurse(min1, first, rest)
    return recurse(min1, min2, rest)

def second_smallest(list):
    if len(list) < 2:
        raise ValueError("too few elements to find second_smallest")
    a, b, rest = list[0], list[1], list[2:]
    if b < a:
        return recurse(b, a, rest)
    else:
        return recurse(a, b, rest)

Такое решение не является особенно Pythonic - это скорее функциональный стиль программирования.

Наконец, вы можете передать аргументы в начале списка и объединить две функции, чтобы получить то решение, которое вы ищете:

def second_smallest(list):
    if len(list) < 2:
        raise ValueError("too few elements to find second_smallest")
    a, b = list[0], list[1]
    a, b = min(a,b), max(a,b)
    if len(list) == 2:
        return b
    c, rest = list[2], list[3:]
    if c < a:
        return second_smallest([c,a]+rest)
    if c < b:
        return second_smallest([a,c]+rest)
    return second_smallest([a,b]+rest)

Обратите внимание, что эта функция выполняет некоторую избыточную работу, поскольку она не может знать, вызвана ли она первой, или если она вызывает рекурсивно. Кроме того, + создает новый список, поэтому этот код, скорее всего, займет время O (n ^ 2) для списка размером n.

Ответ 2

Вы можете использовать классический разрыв и побеждать. Пусть f(x) - функция, возвращающая кортеж (a,b), содержащий наименьший и следующий наименьший элементы в списке x.

Базовые случаи: когда x имеет 0 или 1 элемент. За базовым случаем разделите список на 2, повторите поиск, чтобы найти наименьшие два элемента каждой половины, затем выберите в качестве результата минимум 2 из этих 4:

def min2(x):
  if len(x) == 0: return sys.maxsize, sys.maxsize
  if len(x) == 1: return x[0], sys.maxsize
  m = int(len(x)/2)
  a1, b1 = min2(x[:m])
  a2, b2 = min2(x[m:])
  return (a1, min(b1, a2, b2)) if a1 < a2 else (a2, min(b2, a1, b1))

def secondSmallest(x)
  return min2(x)[1]

Здесь я использую sys.maxsize как "бесконечность".

Ответ 3

Вы можете использовать флаг для отслеживания того, находитесь ли вы на самом внешнем уровне вызовов.

def second_smallest(numbers, top_level=True):
    # Do your stuff and call `second_smallest(numbers[1:], False)` for any recursions.
    # When it comes to returning a value from the function, use the following.

    if top_level:
        return result[0]   # what your function ultimately returns
    return result          # [second, first] since you're still in recursive calls

Ответ 4

Я могу думать о нескольких путях. Медленным является поиск наибольшего значения данного списка, а затем повторение оставшейся части списка. Если длина списка равна 2, не выполняйте рекурсивный вызов.

Быстрее - найти наименьший элемент, вернуться в оставшуюся часть списка, итерации только дважды. Напишите процедуру, чтобы найти этот n th самый маленький элемент таким образом, а затем заверните его в подпрограмму, которая вызывает его с n = 2.

Достаточно ли такого запуска?

Ответ 5

Один из возможных способов - создать функцию с тремя параметрами: list и необязательными smallest_value и second_smallest. В функции pop первый элемент сравнивает ее с наименьшим и вторым наименьшим значением и при необходимости меняет значения. Затем снова вызовите функцию с новыми list, smallest и second_smallest. Рекурсия должна заканчиваться, когда список пуст и возвращает вторую наименьшую.

Есть несколько сложных состояний (когда один/оба значения еще не установлены). Но я думаю, что детали реализации, и вы можете снова спросить, есть ли у вас какие-либо проблемы с его кодированием.

Ответ 6

Что я понимаю из вопроса: - 1. Решение должно быть рекурсивным 2. Отсутствие внутренней функции взлома 3. Он должен вернуть второй наименьший и принять список в качестве параметра Мой код для решения этой проблемы -

from inspect import getouterframes, currentframe
def second_smallest(ls):
    level = len(getouterframes(currentframe(1)))

    if len(ls)<2:
        return None
    if len(ls) == 2:
                if level == 1:
                    return max(ls)
                else:
                    return min(ls), max(ls)
    else:
        m,n = second_smallest(ls[1:])
        if ls[0]<=m:
            n = m
            m = ls[0]
        elif ls[0] < n:
            n = ls[0]
        if level == 1:
            return n
        return m,n

Примечание. Этот код работает, если вы запустите файл программы python

Ответ 7

Вы можете сделать что-то в этом направлении:

def rmin(li, n=2):
    def _rmin(li):
        if len(li) == 1:
            return li[0]
        else:
            m = _rmin(li[1:])
            return m if m < li[0] else li[0]  

    a=[]        
    for i in range(n):
        x=_rmin([e for e in set(li) if e not in a]) 
        a.append(x)
    return x