這是我第一次實習面試的時候被問到的算法題,現在想想當時還是很年輕啊。
鏈表是數據結構的基礎而且變化多端,可以考察的點非常的多,單鏈表反轉應該是在面試中出現次數比較多的一道題了,我覺得它是在考一個人的基礎,也考察的思維靈敏度。
例如給定1 -> 2 -> 3 -> 4 -> 5,轉換成5 -> 4 ->3 -> 2 -> 1。
比較巧妙的一種方法就是遞歸判斷,假設已經遞歸到最後一步1 -> 2 <- 3 <- 4 <- 5,只要把節點2指向節點1就可以了。有n 個節點,那麼如果第一個節點後面的
n-1 個節點已經正確倒轉了的話,我只要處理第一和第二個節點的指向關係就可以了。要是n-1個節點正確倒轉,就先要n-2個節點倒轉。。。這樣遞歸下去直到只剩下最後一個節點,你可以看做它不是倒轉也可以把它看做倒轉。這就是遞歸的基線條件,而上面講到的就是這個算法的遞歸條件,而且這樣做也不用去考慮邊界值問題。下面是代碼實現:
節點結構:
package p_15_reverselist;
public class Node {
int val;
Node next;
}
構建鏈表:
package p_15_reverselist;
public class InitializeList {
public Node createList(int nodeNum) {
if(nodeNum <= 0) {
return null;
}
Node head = null;
int val = 0;
Node node = null;
while(nodeNum > 0) {
if(head == null) {
head = new Node();
head.val = val;
head.next = null;
node = head;
}else {
node.next = new Node();
node = node.next;
node.val = val;
node.next = null;
}
val++;
nodeNum--;
}
return head;
}
public void printList(Node node){
while(node != null) {
System.out.print(node.val+"->");
node = node.next;
}
System.out.println("null");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
InitializeList init = new InitializeList();
Node head = init.createList(6);
init.printList(head);
ReverseList rl = new ReverseList(head);
init.printList(rl.getReverseList());
}
}
反轉列表:
package p_15_reverselist;
public class ReverseList {
private Node head;
private Node newHead;
public ReverseList(Node head){
this.head = head;
}
public Node reverse(Node node) {
if(node == null || node.next == null) {
newHead = node;
return node;
}
Node head = reverse(node.next);
head.next = node;
node.next = null;
return node;
}
public Node getReverseList(){
reverse(head);
return newHead;
}
}