1. 程式人生 > >劍指offer題解(十):C++&java

劍指offer題解(十):C++&java

二叉搜尋樹的後序遍歷序列

題目描述

輸入一個整數陣列,判斷該陣列是不是某二叉搜尋樹的後序遍歷的結果。假設輸入的陣列的任意兩個數字都互不相同。

例如,下圖是後序遍歷序列 3,1,2 所對應的二叉搜尋樹。

解題思路

BST的後序序列的合法序列是,對於一個序列S,最後一個元素是x (也就是根),如果去掉最後一個元素的序列為T,那麼T滿足:T可以分成兩段,前一段(左子樹)小於x,後一段(右子樹)大於x,且這兩段(子樹)都是合法的後序序列。完美的遞迴定義

c++

class Solution {
private:
  bool func(vector<int>
&a, int l, int r) { if(l >= r) return true; int i = r; while(i > l && a[i - 1] > a[r]) --i; for(int j = i - 1; j >= l; --j) if(a[j] > a[r]) return false; return func(a, l, i - 1)&&func(a,i,r-1); } public: bool VerifySquenceOfBST(vector<int
>
sequence) { if(!sequence.size()) return false; return func(sequence, 0, sequence.size() - 1); } };

java

public boolean VerifySquenceOfBST(int[] sequence) {
    if (sequence == null || sequence.length == 0)
        return false;
    return verify(sequence, 0, sequence.length - 1
); } private boolean verify(int[] sequence, int first, int last) { if (last - first <= 1) return true; int rootVal = sequence[last]; int cutIndex = first; while (cutIndex < last && sequence[cutIndex] <= rootVal) cutIndex++; for (int i = cutIndex + 1; i < last; i++) if (sequence[i] < rootVal) return false; return verify(sequence, first, cutIndex - 1) && verify(sequence, cutIndex, last - 1); }

二叉樹中和為某一值的路徑

題目描述

輸入一顆二叉樹和一個整數,打印出二叉樹中結點值的和為輸入整數的所有路徑。路徑定義為從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。

下圖的二叉樹有兩條和為 22 的路徑:10, 5, 7 和 10, 12

解題思路

class Solution {
private:

  void dfs(TreeNode* root,int s,vector<vector<int>> &ret,vector<int> &trace)
  {
       trace.push_back(root->val);
       if(root->left == NULL&& root->right==NULL)
       {
         if(root->val == s)
              ret.push_back(trace);
       }
       if(root->left != NULL)
              dfs(root->left, s-root->val, ret, trace);

       if(root->right != NULL)
              dfs(root->right, s-root->val, ret, trace);

      trace.pop_back();  
  }
public:
    vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {

      vector<vector<int>> res;
      vector<int> trace;

      if(root) dfs(root,expectNumber,res,trace);

      return res;

    }
};

java

private ArrayList<ArrayList<Integer>> ret = new ArrayList<>();

public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int target) {
    backtracking(root, target, new ArrayList<>());
    return ret;
}

private void backtracking(TreeNode node, int target, ArrayList<Integer> path) {
    if (node == null)
        return;
    path.add(node.val);
    target -= node.val;
    if (target == 0 && node.left == null && node.right == null) {
        ret.add(new ArrayList(path));
    } else {
        backtracking(node.left, target, path);
        backtracking(node.right, target, path);
    }
    path.remove(path.size() - 1);
}

python

def pathSum(self, root, sum):
    if not root:
        return []
    res = []
    self.dfs(root, sum, [], res)
    return res

def dfs(self, root, sum, ls, res):
    if not root.left and not root.right and sum == root.val:
        ls.append(root.val)
        res.append(ls)
    if root.left:
        self.dfs(root.left, sum-root.val, ls+[root.val], res)
    if root.right:
        self.dfs(root.right, sum-root.val, ls+[root.val], res)

複雜連結串列的複製

題目描述

輸入一個複雜連結串列(每個節點中有節點值,以及兩個指標,一個指向下一個節點,另一個特殊指標指向任意一個節點),返回結果為複製後複雜連結串列的 head。

解題思路

c++

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if(pHead == NULL)
            return NULL;
        RandomListNode * cur = pHead;
        //插入新節點
        while(cur!=NULL)
        {
            RandomListNode *newnode = new RandomListNode(cur->label);
            newnode->next = cur->next;
            cur->next = newnode;
            cur = newnode->next;
        }
        //建立random連結
        cur = pHead;
        while(cur!=NULL)
        {
            RandomListNode *newnode = cur->next;
            if(cur->random != NULL)
                newnode->random = cur->random->next;
            cur = newnode -> next;
        }
        //拆分
        cur = pHead;
        RandomListNode *pclonehead = pHead->next;
        while(cur->next != NULL)
        {
            RandomListNode *next = cur->next;
            cur->next = next ->next;
            cur = next;
        }
        return pclonehead;
    }
};

java

public RandomListNode Clone(RandomListNode pHead) {
    if (pHead == null)
        return null;
    // 插入新節點
    RandomListNode cur = pHead;
    while (cur != null) {
        RandomListNode clone = new RandomListNode(cur.label);
        clone.next = cur.next;
        cur.next = clone;
        cur = clone.next;
    }
    // 建立 random 連結
    cur = pHead;
    while (cur != null) {
        RandomListNode clone = cur.next;
        if (cur.random != null)
            clone.random = cur.random.next;
        cur = clone.next;
    }
    // 拆分
    cur = pHead;
    RandomListNode pCloneHead = pHead.next;
    while (cur.next != null) {
        RandomListNode next = cur.next;
        cur.next = next.next;
        cur = next;
    }
    return pCloneHead;
}

二叉搜尋樹與雙向連結串列

題目描述

輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成一個排序的雙向連結串列。要求不能建立任何新的結點,只能調整樹中結點指標的指向。

java

private TreeNode pre = null;
private TreeNode head = null;

public TreeNode Convert(TreeNode root) {
    if (root == null)
        return null;
    inOrder(root);
    return head;
}

private void inOrder(TreeNode node) {
    if (node == null)
        return;
    inOrder(node.left);
    node.left = pre;
    if (pre != null)
        pre.right = node;
    pre = node;
    if (head == null)
        head = node;
    inOrder(node.right);
}

c++

//直接用中序遍歷
public class Solution {
    TreeNode head = null;
    TreeNode realHead = null;
    public TreeNode Convert(TreeNode pRootOfTree) {
        ConvertSub(pRootOfTree);
        return realHead;
    }

    private void ConvertSub(TreeNode pRootOfTree) {
        if(pRootOfTree==null) return;
        ConvertSub(pRootOfTree.left);
        if (head == null) {
            head = pRootOfTree;
            realHead = pRootOfTree;
        } else {
            head.right = pRootOfTree;
            pRootOfTree.left = head;
            head = pRootOfTree;
        }
        ConvertSub(pRootOfTree.right);
    }
}

相關推薦

offer題解C++&java

二叉搜尋樹的後序遍歷序列 題目描述 輸入一個整數陣列,判斷該陣列是不是某二叉搜尋樹的後序遍歷的結果。假設輸入的陣列的任意兩個數字都互不相同。 例如,下圖是後序遍歷序列 3,1,2 所對應的二叉搜尋樹。 解題思路 BST的後序序列的合法序列是

offer題解c++&java

二叉樹的映象 題目描述 操作給定的二叉樹,將其變換為源二叉樹的映象。 解題思路 c++ class Solution { private: void swapfun(TreeNode *root) { T

offer題解java&c++

矩陣中的路徑 題目描述 請設計一個函式,用來判斷在一個矩陣中是否存在一條包含某字串所有字元的路徑。路徑可以從矩陣中的任意一個格子開始,每一步可以在矩陣中向左,向右,向上,向下移動一個格子。如果一條路徑經過了矩陣中的某一個格子,則該路徑不能再進入該格子。

offer題解c++&java

序列化二叉樹 題目描述 請實現兩個函式,分別用來序列化和反序列化二叉樹 對於序列化:使用前序遍歷,遞迴的將二叉樹的值轉化為字元,並且在每次二叉樹的結點不為空時,在轉化val所得的字元之後新增一個’ , ‘作為分割。對於空節點則以 ‘#’ 代替。 對

offer系列16反轉連結串列

題目描述 輸入一個連結串列,反轉連結串列後,輸出新連結串列的表頭。 樣例 輸入: 1->2->3->4->5->NULL 輸出: 5->4->3->2->1->NULL 思路分析 雙指標法,pre指

offer系列4重建二叉樹

題目描述 輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。 樣例分析 例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回{1,2,

Offer題解陣列問題

#include<vector> using namespace std; #pragma region 二維陣列中的查詢 二維陣列 //在一個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序, //每一列都按照從上到下

Offer題解字串問題

#include<vector> using namespace std; // getline(cin, str); //一行一行輸入可輸入空格 #pragma region 替換空格 字串 //請實現一個函式,將一個字串中的每個空格替換成“

offer系列47求1+2+3+...+n

題目描述 求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等關鍵字及條件判斷語句(A?B:C)。 樣例 輸入5 輸出15 思路分析 方法一:利用Math類的api實現n(n+1),即Math.pow(

offer題解十三

開篇 十幾天沒有刷題了,今天又可以開始刷題啦 連續子陣列的最大和 題目描述 HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了:在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好

offer系列最小的k個數, 連續子陣列的最大和,整數中1出現的個數

最小的k個數 題目描述 輸入n個整數,找出其中最小的K個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,。 解題思路: 思路1,這一題應用堆排序演算法複雜度只有O(nlog k),堆是完全二叉樹的一種,最大堆就是最上面的數是最大的,該方法基於二

offer系列二叉搜尋樹與雙向連結串列, 字串的排序

二叉搜尋樹與雙向連結串列 題目描述 輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成一個排序的雙向連結串列。要求不能建立任何新的結點,只能調整樹中結點指標的指向。 解題思路: 由於輸入的一個二叉搜尋樹,其左子樹小於右子樹的值,這位後面的排序做了準備,因為只需要中序遍歷即可,將所有 的節點儲存

offer系列翻轉單詞順序列,撲克牌順子,孩子們的遊戲圓圈中最後剩下的數

翻轉單詞順序列 題目描述 牛客最近來了一個新員工Fish,每天早晨總是會拿著一本英文雜誌,寫些句子在本子上。同事Cat對Fish寫的內容頗感興趣,有一天他向Fish借來翻看,但卻讀不懂它的意思。例如,“student. a am I”。後來才意識到,這傢伙原來把句子單詞的順序翻轉了,正確的句

offer系列和為S的連續正數序列,和為s的兩個數字,左旋轉字串

和為S的連續正數序列 題目描述 小明很喜歡數學,有一天他在做數學作業時,要求計算出9~16的和,他馬上就寫出了正確答案是100。但是他並不滿足於此,他在想究竟有多少種連續的正數序列的和為100(至少包括兩個數)。沒多久,他就得到另一組連續正數和為100的序列:18,19,20,21,22。現

offer系列二叉樹的深度,平衡二叉樹,陣列中只出現一次的數字

二叉樹的深度 題目描述 輸入一棵二叉樹,求該樹的深度。從根結點到葉結點依次經過的結點(含根、葉結點)形成樹的一條路徑,最長路徑的長度為樹的深度。 解題思路: 利用遞迴實現。如果一棵樹只有一個結點,那麼它的深度為1。遞迴的時候無需判斷左右子樹是否存在,因為如果該節點 為葉節點,它的左右

offer系列求1+2+3+...+n,不用加減乘除做加法,把字串轉換成整數

求1+2+3+...+n 題目描述 求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等關鍵字及條件判斷語句(A?B:C)。 解題思路: 法一:利用python的特性 法二:用兩個函式,一個遞迴,另一個終止遞迴。如果對n連續進

offer題解連續子陣列的最大和

題目描述 HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了:在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數,並期望旁邊的正數會彌補它呢?例如:{6,-3,-2,7,-

offer題解陣列中出現次數超過一半的數字

題目描述 陣列中有一個數字出現的次數超過陣列長度的一半,請找出這個數字。例如輸入一個長度為9的陣列{1,2,3,2,2,2,5,4,2}。由於數字2在陣列中出現了5次,超過陣列長度的一半,因此輸出2。如果不存在則輸出0。   解題思路   先找到出現次數最多

offer題解二叉樹與雙向連結串列

題目描述 輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成一個排序的雙向連結串列。要求不能建立任何新的結點,只能調整樹中結點指標的指向。   解題思路   中序遍歷搜尋二叉樹,用pre儲存中序遍歷的前一個節點,cur為當前節點,然後使pre->right=cu

offer題解複雜連結串列的複製

題目描述 輸入一個複雜連結串列(每個節點中有節點值,以及兩個指標,一個指向下一個節點,另一個特殊指標指向任意一個節點),返回結果為複製後複雜連結串列的head。(注意,輸出結果中請不要返回引數中的節點引用,否則判題程式會直接返回空) 思路 新建一個連結串列,先不管random指標,根據n