劍指offer個人題解1

2021-09-19 19:31:54 字數 3644 閱讀 9364

在乙個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成乙個函式,輸入這樣的乙個二維陣列和乙個整數,判斷陣列中是否含有該整數。

其實這個題目是非常有規律的,所以才可以用複雜度更小的方法來實現。由於其每行自左向右遞增,每列自上而下遞增,所我們可以設定乙個初始位置,讓他不在(0,0)的位置,而是第一列最後乙個位置,如果實際數比它大了,那就向右查詢,否則向上查詢。

bool find(int target, vector> array) 

}return false;

}

void replacespace(char *str,int length) 

int newlen=realen+count*2;

if(length=0;j--)

}str[newlen]='\0';

}

輸入乙個鍊錶,按煉錶值從尾到頭的順序返回乙個arraylist。

其實很容易想到,可以使用filo的堆疊來進行處理。

vectorprintlistfromtailtohead(listnode* head) 

int len= arr.size();

for(int i=0;i輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列和中序遍歷序列,則重建二叉樹並返回。

我們根據前序遍歷的特點可以發現,前序遍歷的第乙個數字一定是這個二叉樹的根節點;然後根據中序遍歷的特點可發現,根節點左側的數字一定是左子樹,右側一定是右子樹。然後將中序遍歷以根節點為中心劃分成兩個部分,這又是兩個子樹,然後這個子樹又可以根據前序遍歷找到各個子樹的根節點……以此類推,這非常適合有遞推來實現。

就拿這個例子來說。

前序遍歷:序號0

1234

567內容

1247

3568

中序遍歷:序號0

1234

567內容

4721538

6 這又就把中序遍歷分為了4/7/2和5/3/8/6兩個部分。然後考慮4/7/2這個部分,前序遍歷的第2個數字是劃分4/7/2的數字,這樣,2是這個子樹的根節點,4/7都位於左子樹。

然後再看右子樹,也就是3/5/6/8這四個數字。同理可以得出,3是右子樹的根節點,然後5在左子樹,8/6在右子樹。再去8/6這個子樹看,根據前序遍歷可以看到6為子樹的根節點,根據中序遍歷可以看到,8為子樹的左結點。

接下來考慮**實現問題。首先肯定要判斷所給的兩個陣列是不是空,若是空肯定是個空樹,否則繼續進行。我們可以使用類裡面的乙個私有函式來進行具體的重建功能,而這個函式的引數自然是前序遍歷結果、起始位置、結束位置、中序遍歷結果、起始位置、結束位置。

當然作為剛開始的時候,起始位置肯定是0,結束位置肯定是length-1

使用這個私有函式進行遞迴,肯定有停止遞迴的條件,那就是開始位置大於結束位置的時候,自然就代表迭代結束了。

然後新建乙個treenode,第乙個節點自然是前序遍歷的第乙個節點,所以可以:

treenode root=new treenode(pre[startpre]);

接下來自然要開始進行判斷,尋找前序遍歷和中序遍歷相等值的位置,由於前序遍歷裡面的點都可以作為中序遍歷裡面的根節點,所以我們只需要在中序遍歷裡面找到與前序遍歷中值相等的位置,就是該子樹的根節點的位置,就可以根據這個點劃分左子樹和右子樹了。而中序遍歷中到的根節點的位置i左側有幾個數字就是左子樹有幾個元素,右邊有幾個數字就是右子樹有幾個元素

對於左子樹來說,左子樹的起始位置自然是startpre的下乙個位置,而結束是startpre+i-startin(startpre是位置,i-startin是從中序遍歷中看左子樹有幾個元素),而中序遍歷的開始位置自然是startin,結束位置是i-1。

對於右子樹來說,中序遍歷的起始位置自然是i+1,結束位置是endin;而對於前序遍歷來說,自然是startpre+左子樹的元素數+1,而左子樹我們知道是i-startin了,所以起始位置是startpre+i-startin+1,結束位置自然是endpre。

於是,完成了這個程式的編寫。

public treenode reconstructbinarytree(int  pre,int  in) 

//前序遍歷和中序遍歷序列

private treenode reconstructbinarytree(int pre,int startpre,int endpre,int in,int startin,int endin)

return root;

}

用兩個棧來實現乙個佇列,完成佇列的push和pop操作。 佇列中的元素為int型別。

思路很簡單,就是用兩個堆疊,push直接push進去就可以。由於佇列是fifo,而堆疊是filo,所以只要使用push後的堆疊再push到另乙個堆疊裡面,這個時候pop出來的順序總體上來說就是fifo了。

public:

void push(int node)

int pop()

int res=stack2.top();

stack2.pop();

return res;}

private:

stackstack1;

stackstack2;

把乙個陣列最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。 輸入乙個非減排序的陣列的乙個旋轉,輸出旋轉陣列的最小元素。 例如陣列為的乙個旋轉,該陣列的最小值為1。 note:給出的所有元素都大於0,若陣列大小為0,請返回0。

最傻瓜的方式就是直接進行比較了,但是這樣的時間複雜度為o(n),我們可以考慮降低複雜度。考慮到這個旋轉陣列本質上是乙個基本有序的陣列,所以我們可以考慮借鑑二分查詢的思想。

令low=0,high=len-1,即兩個指標分別指向陣列的開頭和結尾。我們令mid=(low+high)/2。

int minnumberinrotatearray(vectorrotatearray) 

return rotatearray[low];

}

給定乙個double型別的浮點數base和int型別的整數exponent。求base的exponent次方。

假如我們要計算313,我們既可以直接乘(複雜度為o(n)),也可以用快速演算法降低複雜度。方法是怎樣的呢?

我們關注指數部分,13=(1101)2所以313=3(1000)2

3(0100)2

3(0001)2

。這樣的話,我們可以將exponent&1操作,如最低位為1,那麼就是做ans=ans * base,否則不做。然後對exponent進行右移,每右移1位,base=base * base,這樣若為1,則ans=base;若為101,則為ans=base * (base * base)。然後就可以得到結果了,**如下。

double power(double base, int exponent)

return exponent<0?(1/ans):ans;

}

劍指offer部分題解(1)

題目描述 輸入乙個正整數陣列,把陣列裡所有數字拼接起來排成乙個數,列印能拼接出的所有數字中最小的乙個。例如輸入陣列,則列印出這三個數字能排成的最小數字為321323。思路 注意點class solution string printminnumber vector int numbers sort ...

劍指offer題解

在乙個二維陣列中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成乙個函式,輸入這樣的乙個二維陣列和乙個整數,判斷陣列中是否含有該整數。思路 這題較好的思路有兩個,乙個是最容易想到的nlog,枚舉行,二分列。另一種就是從左下角逐步列舉,如果大於目標值就向上走,小於目標值...

劍指Offer題解索引

陣列中重複的數字 二維陣列中的查詢 構建乘積陣列 替換空格 字元流中第乙個不重複的字元 表示數值的字串 斐波那契數列 跳台階 跳台階 矩形覆蓋 從尾到頭列印鍊錶 刪除鍊錶中重複的結點 鍊錶中環的入口結點 把二叉樹列印成多行 按之字形順序列印二叉樹 對稱的二叉樹 二叉樹的下乙個結點 資料流中的中位數 ...