劍指offer3.4-代碼的魯棒性

題目java

輸入一個鏈表,輸出該鏈表中倒數第k個結點。 

思路數組

1.首先想到的是走到鏈表的尾端,再由尾端回溯k步。但是鏈表的節點定義看出這是單向鏈表,結點只有從前日後的指針,所以不能這樣走。this

2.只能從頭節點開始遍歷鏈表。那麼咱們能夠先獲取鏈表的結點數,就能夠計算從前日後是須要走多少步了。可是這樣須要遍歷兩次鏈表spa

3.爲了實現只遍歷一次鏈表,咱們仍是像以前翻轉數組同樣,設立兩個指針。第一個指針從鏈表的頭指針開始遍歷向前走k-1,第二個指針始終指向頭結點。當第一個指針指向k個結點的時候,兩個指針同時向前遍歷,這樣確保兩個指針距離爲k。那麼當第一個指針指向末尾結點時,第二個指針指向的就是倒數第k個結點。指針

4.而且須要注意潛在崩潰的風險。當輸入的head爲空指針時,代碼會試圖訪問空指針的內存空間;輸入的鏈表結點數小於k,for循環中會在鏈表上向前走k-1步,一樣會形成空指針;當k是unsigned int型時,輸入的參數k爲0,此時for循環的k獲得的不是-1,而是0xFFFFFFFF(4294967295),執行次數會很是很是大,形成程序崩潰。code

解法blog

/*    public class ListNode {
        int val;
        ListNode next = null;
 
        ListNode(int val) {
            this.val = val;
        }
    }*/
 
public class Solution {
 
    public ListNode FindKthToTail(ListNode head,int k) {
        if(head == null)
            return null;
        ListNode P1=head;
        while(P1!=null && k-->0)
            P1=P1.next;
        //若是k大於鏈表的長度
        if(k>0){
            return null;
        }
        ListNode P2=head;
        while(P1!=null){
            P1=P1.next;
            P2=P2.next;
        }
        return P2;
    }
}

 

題目遞歸

輸入一個鏈表,反轉鏈表後,輸出新鏈表的表頭。 

思路內存

1.反轉後鏈表的頭結點就是原始鏈表的尾節點,即next爲NULL的結點。io

2.一樣能夠採用遞歸,使當前head的next指向null,不斷反轉。

3.或者採用頭插法。構建一個新的指針用來指向

解法

/*
public class ListNode {
    int val;
    ListNode next = null;
 
    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode ReverseList(ListNode head) {
        if(head == null || head.next == null)
            return head;
        ListNode next=head.next;
        head.next=null;
        ListNode newHead=ReverseList(next);
        next.next=head;
        return newHead;
    }
    public ListNode ReverseList(ListNode head) {
 
 
           ListNode newList = new ListNode(- 1 );
 
 
           while (head != null ) {
 
 
               ListNode next = head.next;
 
 
               head.next = newList.next;
 
 
               newList.next = head;
 
 
               head = next;
 
 
           }
 
 
         return newList.next;
 
 
    }  
}

題目

輸入兩棵二叉樹A,B,判斷B是否是A的子結構。(ps:咱們約定空樹不是任意一個樹的子結構)

思路

 判斷A中有一部分子樹的結構與B是同樣的,則採用遞歸。

1.在樹A中找到與B的根結點值相同的結點R

2.判斷樹A中以結點R爲根結點的子樹是否包含與B同樣的結構。根據根結點找到相同結構的部分,再往下比較

解答

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }
}
*/
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        boolean result=false;
        //檢查空指針
        if(root1!=null && root2!=null){
            //當A的某一結點的值和樹B的頭結點值相同,則作第二步判斷
            if(root1.val == root2.val)
                //判斷樹A中以R爲根結點的子樹是否是和樹B具備相同的結構
                result = DoesTree1HaveTree2(root1, root2);
            //若是當前根節點不相同,就看root1的左結點和root2的根節點比較。就是低一層比較
            if(!result)
                result=HasSubtree(root1.left, root2);
            if(!result)
                result=HasSubtree(root1.right, root2);
        }
        return result;
    }
    
    public boolean DoesTree1HaveTree2(TreeNode root1, TreeNode root2){
        //遞歸的終止條件:即到達了樹A或樹B的葉結點
        if(root2 == null)
            return true;
        if(root1 == null)
            return false;
        //若結點R的值和樹B的根結點不相同,那麼它們確定不具備相同的結點
        if(root1.val != root2.val)
            return false;
        //若是值相同,那麼遞歸判斷它們各自的左右結點值是否是相同
        return DoesTree1HaveTree2(root1.left, root2.left) &&
               DoesTree1HaveTree2(root1.right, root2.right);
    } 
}

題目

輸入兩個單調遞增的鏈表,輸出兩個鏈表合成後的鏈表,固然咱們須要合成後的鏈表知足單調不減規則。 

思路

1.鏈表的合併過程以下,從合併兩個鏈表的頭結點開始,當鏈表1的頭結點的值小於鏈表2的頭結點值,所以鏈表1的頭結點將爲合併後鏈表的頭結點。剩餘結點中,鏈表2的頭結點值小於鏈表1的頭結點的值,所以鏈表2的頭結點是剩餘結點的頭結點,把這個結點和以前合併好的鏈表的尾節點連接起來。不斷比較兩個鏈表的頭結點的值。

2.爲了防止訪問空指針指向的內存空間引發的崩潰,須要處理當兩個鏈表爲空鏈表時的結果,當都爲空鏈表時,合併的結果就是空鏈表。

解法

/*
public class ListNode {
    int val;
    ListNode next = null;
 
    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if(list1==null)
            return list2;
        if(list2==null)
            return list1;
        if(list1.val<=list2.val){
            list1.next=Merge(list1.next,list2);
            return list1;
        }
        else{
            list2.next=Merge(list1,list2.next);
            return list2;
        }
    }
}
相關文章
相關標籤/搜索