劍指offer解題思路錦集11-20題
又來更新劍指offer上的題目思路啦。
11、【二進制中1的個數】
題目:輸入一個整數,輸出該數二進制表示中1的個數。其中負數用補碼表示。
eg:NumberOf1(1)=1 NumberOf1(2)=0 NumberOf1(3)=2 NumberOf1(4)=1 NumberOf1(5)=2 NumberOf1(6)=2 NumberOf1(7)=3
思路:每次都將數字n的最後一位1反轉成0,不斷反轉到這個數字變成0,然後我們統計反轉了多少次,這樣不就可以成功得到這個數字有多少位了嗎?
難點:如何反轉一個數字的最後一位1,解決方案如下:
n = n & (n - 1);
代碼:
int NumberOf1(int n) { int number = 0; while (n != 0) { n = n & (n - 1); ++number; } return number; }
思路2:可不可以嘗試不去改變這個數字呢?答案也可以的。假設是int類型,如果我循環32次,判斷每個位是否為1,這樣不也可以得到這個數字有多少位為1嗎?誠然,這樣也是存在著缺點的。
缺點:比思路1的時間復雜度略高,不過也是常數級別的,因為數字的位數是有限制的,兩者可能系數上存在著差別吧!~~~還有一個缺點,就是這樣的代碼移植性較差~~
存在坑:
(temp & n) != 0
這裏的括號不能去掉,因為&的優先級比 != 低。。。。
代碼:
int NumberOf1(int n) { int number = 0; int temp = 1; for (int i = 0; i < 32; ++i) { if ((temp & n) != 0) { ++number; } temp = temp<<1; } return number; }
12、【數值的整數次方】
給定一個double類型的浮點數base和int類型的整數exponent。求base的exponent次方。
例子:2^10
思路1:2*2*2*2*2*2*2*2*2*2,循環N次即可。時間復雜度O(n)沒啥好說的,跳過。
思路2: 分治想法,假設是求a^n
如果n為偶數,那麽轉化成求x=a^(n/2),然後返回x*x即可。
如果n為奇數,那麽轉化成求x=a^(n-1/2),然後返回x*x*a即可。
時間復雜度是O(lgn)。。。怎麽證明?
應用算法導論中的主方法即可。
這裏,有T(n) = T(n/2) + 1,即 b = 2, a = 1,f(n)=1。因此滿足條件2,因此時間復雜度為O(nlogb(a))=O(nlog2(1)*lgn)=O(1*lgn)=O(lgn)。
哈哈,是不是瞬間感覺寫難了。。。。
13、【調整數組順序使奇數位於偶數前面】
題目:輸入一個整數數組,實現一個函數來調整該數組中數字的順序,使得所有的奇數位於數組的前半部分,所有的偶數位於位於數組的後半部分,並保證奇數和奇數,偶數和偶數之間的相對位置不變。
思路:兩個數組,一個按順序保存奇數,另一個按順序保存偶數。。。時間復雜度O(N),空間復雜度O(N)。
思路2:創建一個數組,循環2次,第一次只掃描奇數,丟進數組中。第二次只掃描偶數,丟進數組。。十分簡單。。。
思路3:類似冒泡算法,前偶後奇數就交換。
void reOrderArray(vector<int> &arr) {//雙指針 int n = arr.size(); for(int i = 0; i < n; ++i) { for(int j = 0; j < n-i-1; ++j) { if(arr[j]%2 == 0 && arr[j+1]%2 == 1) swap(arr[j],arr[j+1]); } } }
思路4:兩個指針咯,一個指針1從頭到尾,另外一個指針2從尾到頭,如果指針1發現偶數,那麽停下來,如果指針2發現奇數,那麽也停下來。再交換兩個指針指向的數就Ok了。
問題:這樣是真的可以嗎?答案是不可以的哦~哈哈,因為這樣違反了題目要求——要求奇數和偶數順序不能改變。。。嗯,是的,如果是讓順序可以隨意的話,那麽這就是很nice的解。
14、【鏈表中倒數第k個結點】
題目:輸入一個鏈表,輸出該鏈表中倒數第k個結點。
思路1:遍歷得到鏈表長度n,然後再遍歷一次,給返回第n-k+1個元素。這裏遍歷了兩次,時間復雜度為0(n),空間復雜度為O(1)。
思路2:思路1是否存在優化的地方呢?是存在的,我們可以考慮考慮能不能不遍歷兩次,這時候我們想能不能用空間換時間。
好比,將鏈表轉化成數組保存下來,那麽我們第二次遍歷鏈表操作可以換成獲取數組中的n-k+1個元素操作了,只需要遍歷一次鏈表就可以了。但是這種方法的空間復雜度為O(N)。
思路3:兩個指針,也就是傳說中的快慢指針。一個指針先走k步,然後慢指針才開始跑。快指針到頭了,那麽落後了k步的慢指針不就是倒數第k個元素了嗎?
代碼:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) { if(NULL == pListHead) return NULL; ListNode* pfront = pListHead; ListNode* pend = pListHead; for (int i = 0; i < k; i++) { if(pfront != NULL) { pfront = pfront->next; } else { return NULL;//超出了 } } for(;pfront != NULL;pfront = pfront->next) { pend = pend->next; } return pend; }
15、【反轉鏈表】
輸入一個鏈表,反轉鏈表後,輸出鏈表的所有元素。
A->B->C->D->E A->B->C->D<-E (D->NULL) A->B->C<-D<-E (C->NULL) A->B<-C<-D<-E (B->NULL) A<-B<-C<-D<-E (A->NULL)
代碼
ListNode* ReverseList(ListNode* pHead) { if(pHead == NULL||pHead->next == NULL) return pHead;//得到鏈表尾部 ListNode* tail = ReverseList(pHead->next); pHead->next->next = pHead; pHead->next = NULL; return tail; }
16、【合並兩個排序的鏈表】
輸入兩個單調遞增的鏈表,輸出兩個鏈表合成後的鏈表,當然我們需要合成後的鏈表滿足單調不減規則。
額,這題啥也不用說了吧,,,不就是歸並排序的合並過程麽。。。。直接貼代碼吧。。。
ListNode* Merge(ListNode* pHead1, ListNode* pHead2) { ListNode* res = NULL; ListNode* cur = NULL; ListNode* add = NULL; if(pHead1 == NULL) return pHead2; if(pHead2 == NULL) return pHead1; while(pHead1 != NULL &&pHead2 != NULL)//兩個叠代器 { add = pHead1->val >= pHead2->val ?pHead2:pHead1; if(res == NULL) res = cur = add;////////////第一次才執行 在於選擇一條鏈出來 else { cur->next = add; cur = cur->next; } if(add == pHead1) pHead1=pHead1->next; else pHead2 = pHead2->next; } if(pHead1 != NULL) cur->next = pHead1; if(pHead2 != NULL) cur->next = pHead2; return res; }
17、【樹的子結構】
題目:輸入兩棵二叉樹A,B,判斷B是不是A的子結構。(ps:我們約定空樹不是任意一個樹的子結構)
其實這裏主要是靠對問題的拆分能力。
子函數CompTree:判斷兩棵樹是否相等。
判斷是否為子樹:假設當前節點為根,那麽是否為子結構?
代碼:
class Solution { private: bool CompTree(TreeNode* pRoot1, TreeNode* pRoot2)//判斷2是否為1的子樹。。。。 { if(pRoot2 == NULL) return true; if(pRoot1 == NULL) return false; if(pRoot1->val == pRoot2->val) return CompTree(pRoot1->left,pRoot2->left)&&CompTree(pRoot1->right,pRoot2->right); return false; } public: bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) { if(pRoot1 == NULL ||pRoot2 == NULL ) return false; return CompTree(pRoot1,pRoot2) || HasSubtree(pRoot1->left,pRoot2) || HasSubtree(pRoot1->right, pRoot2); } };
18、
劍指offer解題思路錦集11-20題