带return的递归构建

用个题目具举例子:

一条非递减的链表,请删除链表中带重复值的节点,只保留删减前不重复的节点,返回头结点。

[1 - 2 - 2 - 3] => [1 - 3]

思路:
递归实质就是: 向下遍历,然后向上回溯核心是:[只看当前层]。带返回值的递归,返回值有两种可能:

  1. 返回的是第一步的返回结果;(例1分析)
  2. 返回的是最后一步回溯的结果。
  • 这里举例说明,看代码:
public int testI(int i, boolean flag) {
    if(i >= 5) return i;
    System.out.print(i);
    if (flag) {
        return testI(++i, true);
    } else {
        testI(++i, false);
        return i;
    }
}
  • 当调用函数的flag为false,代码简化成
public int testI(int i, boolean flag) {
    if(i >= 5) return i;
    System.out.print(i);
    testI(++i, false);
    return i;
}
// 012341 

此时对应第一步情况,因为最后是return一个显式的值,那么向下递归后,得到了结果只被上一层递归得到,最终返回的结果就是第一层。

  • 当调用函数的flag为true,代码简化成
public int testI(int i, boolean flag) {
    if(i >= 5) return i;
    System.out.print(i);
    return testI(++i, true);
}
// 012345

对应最后一步情况,每次返回的是testI函数本身的值,最终层的结果,被回溯上去,得到的结果是最终层。
那么这两种情况如何判断呢?
看最终return与下一层有没有关系。

  • 第一种,只是用到了下层,但下层和返回结果没有直接关系(即返回的值或引用没有与下级产生直接关系),则为第一种情况。
  • 若有关系(最常见的就是return 递归函数return testI()),那么返回值就是终结递归的那一条语句(if(i >= 5) return i)。
现在再来看这个题目

因为要返回链表头结点head,显然是第一种(返回第一步),最终返回的第一层就是真实头结点。

那么每一层要做的事情就是:判断当前层有没有相同的多个节点,

  • 若有:将当前层所有相同节点全部删掉,并返回下一层回溯上来的结果(因为复数个节点要全部删掉)。
  • 若没有:保留当前节点并返回给上一层。
  1. 先构建返回条件
if (head == null || head.next == null) return head;
  1. 对当前节点和下一节点进行值的判断,若相等,则删除该节点,并查看下一个节点,直到值不相等。
if (head.val == head.next.val) {
    while (head.next != null && head.val == head.next.val) {
        head = head.next; // 迭代找到下一层的节点
}
// 返回下一层回溯上来的节点
return deleteDuplicates1(head.next);
}
  1. 若不相等,需要保留当前节点,并将下一层的节点接在后面。返回的是当前节点。
else {
// 接下一层的节点
    head.next = deleteDuplicates(head.next);
    return head;
}
  1. 若想要删除重复节点,但只是删除到只剩一个。怎么办呢?显然从第二步的返回值下手,不能直接返回回溯上来的节点,而要拼接一下。
head.next = deleteDuplicates1(head.next);
return head;

你可能感兴趣的:(带return的递归构建)