反转链表也是面试时常问到的题目,题目听上去很简单,想要快速正确的写出来,也确实需要很扎实的基本功。

这类简单的题目既有非递归的实现方法,也有递归的实现方法。

 


非递归实现

非递归实现,模拟的是基本的手动操作, 访问链表中的每一个节点,但是同时要记住当前被访问节点的上一个和下一个节点。这三个指针构成了一个滑动的窗口,当前的值是滑动窗口的中心,上一个节点最终会变成新链表的头节点。代码如下:

public void Reverse()
{
      p = this.Head;
      node prev = null;
      while(p != null)        
       {
             node next = p.next;
             p.next = prev;
             prev = p;
             p = next;    
        }

       this.head = prev;
}
    

递归实现

第一条:每次递归都能将问题规模缩减下来

第二条: 对应递归终止条件,递归必须有个出口,不然会陷入无限递归当中

第三条: 顺着自己的思路,将递归问题细分为更小的递归问题,然后再进行递归调用。

 

伪代码如下:

Result M(Problem prob)
{
    if (<problem can be solved easily>)/*对应终止条件*/
        return <easy solution>;
    // The problem cannot be solved easily.//对应一般情况,再一步进行细分,递归调用
    Problem smaller1 = <reduce problem to smaller problem>//缩小问题规模
    Result result1 = M(smaller1);
    Problem smaller2 = <reduce problem to smaller problem>////缩小问题规模
    Result result2 = M(smaller2);
    ...
    Result finalResult = <combine all results of smaller problem to solve large problem>//综合结果
    return finalResult;
}

 

归纳法来分析这个题目:

Reverse(first) = {

if (first == null) return null;

if (first.next == null) return first;

Node newHead = reverse(first-> next);
first.next.next = first;
first.next = null;
return newHead;

}

下面是反转链表的递归实现:

 

 public void ReverseRecursive()
        {
            this.Head = ReverseInternal(this.Head);
        }

        private Node ReverseInternal(Node fromNode)
        {
            if (fromNode == null)
            {
                return null;
            }

            if (fromNode.Next == null)
            {
                return fromNode;
            }

            Node rest = ReverseInternal(fromNode.Next);
            fromNode.Next.Next = fromNode;
            fromNode.Next = null;
            return rest;
        }

 

posted on 2018-01-07 08:27  xuyanran  阅读(1156)  评论(0编辑  收藏  举报