前一段日子收到cisco的面試,被問到一個問題,對一個單鏈表進行逆置,題目很簡單,最近對遞歸有了一些新的認識,寫下一些感想。
當你拿到一個可以用遞歸解決的問題時,別馬上下手寫程序,基本上這樣都會失敗,你需要停下來思考一下如何用數學表達式也形式化的寫出
遞歸定義。
比如斐波那契數列,遞歸的數學表達式如下:
f(0)=1
f(1)=1
f(n)=f(n-1)+f(n-2)
有了如上的遞歸表達式,寫遞歸就會很簡單。
鏈表逆置也一樣,如 1->2->3->4->5->null,
f(5)= return //返回逆置的鏈表頭結點
f(其他) = <- //f(1)注意有所改變
代碼如下:
Node* reverse(Node* p){
Node* head=p;
if(p->next == null)
return p;
else{
reverse(p->next);
p->next->next = p;
if(p == head)
head->next = null;
}
}
那么遞歸又如何轉為迭代呢?又需要幾個指針?
1->2->3->4->5->null
p=1,q=2,s=3
<-
1<-2 3->4->5
p=2,q=3,s=4
<-
1<-2<-3 4->5
p=3,q=4,s=5
<-
1<-2<-3<-4 5
p=4,q=5,s=null
<-
1<-2<-3<-4<-5
p=5
代碼如下:
Node* reverse(Node* p){
Node* head = p;
Node* q = p->next;
Node* s = q->next;
while(p->next != null){
q->next = p;
p = q;
if(p->next != null){
q = s;
s = s->next;
}
}
return p;
}
迭代完美方案
prev=null,current=head,next=null
null->1->2->3->4->5->null
next=2
null<-1
pre=1,current=2
prev=1,current=2,next=2
null<-1 2->3->4->5->null
next=3
null<-1<-2
pre=2,current=3
prev=2,current=3,next=3
null<-1<-2<-3 4->5->null
next=4
null<-1<-2<-3<-4
pre=3,current=4,next=4
null<-1<-2<-3<-4 5->null
next=5
...........................
node* rev(node *head)
{
node *prev=NULL,*current=head,*next=NULL;
while(current)
{
next=current->next;
current->next=prev;
prev=current;
current=next;
}
return prev;
}
完美~~
