递归讲解与递归实现列表的反转

递归:

  • 特点:当一个复杂的问题可以分解为几个(最简单的就是一个)相对简单的且与原来问题解法相同或者类似的子问题来求解,便称为递归求解。

递归工作栈与递归过程:

  • 在高级语言中,调用函数与被调用函数之间的链接及信息交换需要通过栈来进行。
  • 字数太多,我们直接上图:

递归算法的效率分析:

  • 时间复杂度: 大致为O(2^n) (斐波那契以及汉诺塔问题)
  • 空间复杂度: O(f(n)) ,f(n) 为递归工作栈中记录的个数与问题规模n的函数关系。

分治法:

  • 一种分解-求解的策略,叫做分治法,用来求解递归问题。

分治法满足的三个条件:

(1)能将一个问题转变为一个新的问题,而新的问题与原来的问题解法相同或类同,不同的仅是处理对象(重点),并且这个对象更小,且变化更有规律。 (下面列表反转递归,第二种方法操作的都是同一个列表对象,每次递归操作不同元素)
(2) 可以通过上述转化使问题简化。
(3) 必须有一个明确的递归出口,或称为递归的边界(重点)。

  • 演示:
void p(参数列表)
{
	if(递归结束条件成立) 可直接求解;      // 递归终止条件
	else p(娇小的参数);				// 递归步骤
}

数据结构是递归的(很多可以递归处理)

  • 例如链表, 树形结构等

上解答问题代码:

a = [1, 2, 3, 4, 5, 6, 7, 8]

def rev_list(l):
    if len(l) == 1:
        return l
    elif len(l) == 2:    # 可以省略这一步
        l[0], l[-1] = l[-1], l[0]
        return l
    else:
        return [l[-1]] + rev_list(l[:-1])  # -1 才算是取最后一位之前的所有

# print(rev_list(a))



# 上述方法会不断的进行 l[:-1] 和 [l[-1]] 的操作,不断地进行浅拷贝效率太低,并且并未改变a,而是返回新的列表
# 从快速排序方法中找到的灵感,我们采用双指针针解决这个问题

def reverse(l, low, height):
    """ 用来实现第一个元素 和列表最后一个元素交换位置 """
    pivotkey = l[low]
    l[low] = l[height]   # python里面其实可以一条语句解决 l[low], l[height] = l[height], l[low]
    l[height] = pivotkey

    low +=1
    height -= 1

    return low, height


def reverse_di(l, low, height):
    """ 实现递归 """
    if low <= height:
        low, height = reverse(l, low, height) # 完成一次最前面和最后面位置值的交换
        reverse_di(l, low, height)

def re_reverse(l):
    reverse_di(l, 0, len(l)-1)

re_reverse(a)
print(a)

"""
    基本的思想就是,交换第一个和最后一个位置的元素,完全可以把递归改成一般的 while 循环语句。
    递归的写法,内部会使用隐藏的栈保存调用函数,过多的占用空间,函数间调用也会损耗性能,
    不过递归算法更显而已懂,易于阅读。
"""
  • 不在列出 递归的快速排序。

你可能感兴趣的:(python,基础算法题练习,C,数据结构,算法)