一、定义
递归:是指在函数定义中又调用函数自身的方法。(即A调用A)
迭代:是指重复反馈过程的活动,其目的是逼近所需目标或结果。(通俗一点说,就是为了达到所需目标不断用旧值推导新值的一个重复反馈过程,也可以说是A调用B)
二、运用技巧
运用
适用条件:需解决的问题可转化为一个或多个相同性质的子问题来求解。
使用步骤:确定使用方法,找到并确定对应的三要素。(递归三要素或迭代三要素)
要点
递归三要素:①确定终止条件;②确定返回值;③确定循环过程。
迭代三要素:①确定迭代变量;②确定迭代关系;③确定迭代过程的控制。
三、例题分析
例题
(链接: 力扣-第24题)
分析求解
1.递归解法:
class Solution {
//每次三个节点在变,除终止外
public ListNode swapPairs(ListNode head) {
//1.递归终止条件
if (head == null || head.next == null)return head;
//3.循环过程
//第二个节点
ListNode scend = head.next;
//循环递归
head.next = swapPairs(scend.next);
//指向第一个
scend.next = head;
//2.返回已排序链表
return scend;
}
}
(递归代码上已经奉上,并说明了三要素,一般认真看了题目后应该能看懂,实在看不懂没关系,根据代码画图理解!)
2.迭代解法:
public ListNode swapPairs(ListNode head) {
//判空和判断节点是否为一个
if(head == null || head.next==null){
return head;
}
//保存头节点
ListNode temp = new ListNode();
temp.next = head;
//1.迭代变量
//定义前一个节点和当前节点
ListNode pre = temp;
ListNode cur = head;
//3.迭代过程控制
//遍历链表,两两节点进行交换
while(cur!=null && cur.next!=null){
List<ListNode> list = reListNode(pre,cur);
//迭代关系,迭代的结果作为下一次迭代的初始值
//cur后移两位,pre后移两位
pre = list.get(0);
cur = list.get(1);
}
return temp.next;
}
public List<ListNode> reListNode(ListNode pre, ListNode cur){
//使用临时结点存储当前第一、二、三个结点
ListNode first = cur;
ListNode second = cur.next;
ListNode third = cur.next.next;
//交换
pre.next = second;
second.next = first;
first.next = third;
//返回后移两位的节点
List<ListNode> list = new ArrayList<>();
list.add(first);
list.add(third);
return list;
}
(迭代代码上已经奉上,并说明了三要素,一般认真看了题目后应该能看懂,实在看不懂没关系,根据代码画图理解!ps:此代码可以简化,我是为了方便大家理解才这样写的)
四、二者的关系及优缺点
关系
递归和迭代在一般情况下可以相互转化。(但要注意:①递归里面有迭代,但迭代里面不一定有递归;②正常情况下能使用迭代的坚决不会使用递归,因为递归对空间的消耗很大)
优、缺点
1.递归:
优点 | 缺点 |
---|---|
可读性好,代码简洁 | 所需空间大,可能会出现子问题的重复计算,递归太深时容易栈溢出 |
2.迭代:
优点 | 缺点 |
---|---|
计算效率高,无额外内存开销 | 代码不如递归简洁,有时不容易理解 |