這週做了一些牛客網上劍指offer的題.選取幾道個人覺得比較典型,有意思的題拿出來進行分析.
1.鍊錶中環的入口節點
乙個鍊錶中包含乙個環,請找出這個環的入口節點.
分析:一般答案不那麼顯然的鍊錶題,大多都可以用這種方法解決:派出兩個指標幹活.這道題也是如此,具體是派出快慢2個指標同時出發,快指標一次走兩步,慢指標一次走一步,找出他們第一次相遇的位置,然後就比較容易操作了,之後就是這是乙個小學數學的行程問題了,這裡就不多贅訴,指標的題需要注意下臨界條件,這道題還好.
class solution //判斷是否是環,其實如果題目出的正確的話可以不用這個條件判斷
else
return
null;
}//指標相遇後重新派出兩個速度一樣的指標再度相遇,相遇後的位置便是環的入口
listnode *p1 = head;
listnode *p2 = slow;
while (p1 != p2)
return p1;
}};
2.刪除鍊錶中重複的節點
題目描述
在乙個排序的鍊錶中,存在重複的結點,請刪除該鍊錶中重複的結點,重複的結點不保留,結果返回煉表頭指標。
分析:乍看之下是一道思路非常明確很溫柔的題,實際上這道題坑了我很久才弄出來,說不定有更簡單的思路(不包括重新建乙個鍊錶哈,只能在原始鍊錶上操作),不過我暫時懶得去看答案了,心累…具體思路也是需要排出兩個指標,前鋒負責探路找出重複的節點,殿後的就負責把刪除節點後的鍊錶重新拼接起來,同時還需要設定乙個判斷是否是重複節點bool值…還是直接上程式吧,這道題的細節操作和臨界處理上都花了我不少時間,很難語言描述清楚.
class solution
else
if (p2->val == p2->next->val)
else
}//收尾的臨界情況,漏了也會報錯
if (issame ==
true)
p1->next =
null;
return headnew->next;
}};
補充.後來看了下人家的**,用的是遞迴,遞迴就簡單多了,不管是思想上還是**上都更簡潔,下面給出遞迴的**:
class solution
head->next = deleteduplication(p->next);
return head;
}};
3.二叉樹的下乙個節點
給定乙個二叉樹和其中的乙個結點,請找出中序遍歷順序的下乙個結點並且返回。注意,樹中的結點不僅包含左右子結點,同時包含指向父結點的指標。
分析:1.若該節點包含右子樹,那麼它的下乙個節點必然是這個右子樹中的最左邊的節點.2.若該節點無右子樹,那麼它的下乙個節點只能是它的父節點或往上的節點.這時候又要分類:如果它正好是它父節點的左子節點,那麼它的父節點就是它的下乙個節點,如果不是,那麼只能繼續向上回溯.
class solution
treelinknode* getrightdadnode(treelinknode* node)
treelinknode* getnext(treelinknode* pnode)
else
}};
4.序列化二叉樹
請實現兩個函式,分別用來序列化和反序列化二叉樹
分析:這題採用的是前序遍歷,對於空節點處用0xffffffff進行補足,思想是非常簡單的遞迴,但是反序列化的具體操作卻不是那麼容易,個人認為是二叉樹的遞迴思想中難度最高的題之一了.這道題是看的答案,這裡盜一波人家的**.
class solution
}treenode* dfs2(int* &p)
treenode* res =new treenode(*p);
p++;
res->left=dfs2(p);
res->right=dfs2(p);
return res;
}char* serialize(treenode *root)
treenode* deserialize(char *str)
};
5.資料流中的中位數
如何得到乙個資料流中的中位數?
分析:輸入乙個資料流,實時的計算出資料流的中位數.可以分別建立乙個大頂堆和小頂堆,使得二者各存一半的資料,且大頂堆中的最大值小於等於小頂堆中的最小值,這樣的話中位數始終都是從大頂堆和小頂堆中的top處誕生的,如資料流[1,3,2,4],輸入後在大頂堆中就是[2,1],在小頂堆中就是[3,4],所以中位數就是(2+3)/2=2.5.具體操作見程式.為什麼要用大頂堆和小頂堆?因為在給定的排序陣列中插入數字可以用頂堆的思想達到o(logn)的複雜度.(我怎麼感覺二分法也是logn的複雜度,估計是理解不夠深刻…)
class solution
}k++;
}double getmedian()
else
return (float(l.top() + g.top())/2);
}};
6.機械人的運動範圍
地上有乙個m行和n列的方格。乙個機械人從座標0,0的格仔開始移動,每一次只能向左,右,上,下四個方向移動一格,但是不能進入行座標和列座標的數字之和大於k的格仔。 例如,當k為18時,機械人能夠進入方格(35,37),因為3+5+3+7 = 18。但是,它不能進入方格(35,38),因為3+5+3+8 = 19。請問該機械人能夠達到多少個格仔?
分析:簡單來說就是從起點出發,每次遞迴地向四個方向前進,如果在某個方向遇到停止條件,那麼便在這個方向上便停止,直到所有前進的路勁都達到停止條件…
class solution
return t;
}int count(int thr, int i, int j, int rows, int cols,vector
>& vis)
}int movingcount(int threshold, int rows, int cols)
};
幾道資料結構的演算法題
一問題 給定一組字串,要求求出乙個最短的字串使得它包含所有給出的字串。比如 a bc ca 輸出應該是 bca 2 按照陣列len的記錄長度,在剩下的字串中找出記錄長度最長的 字串,a.如果這個字串包含在string中,該字串已被包含,轉2 b.如果這個字串的長度是1,將該字串與string連線,該...
資料結構幾道程式設計題
先將其中乙個鍊錶的鏈頭按到另乙個鍊錶的尾部,如果他們有交集則會構成乙個環,題目等價於找鍊錶中的環的起始結點。找到後將鍊錶還原。一.兩個長鍊表求交點 考慮環 public listnode getintersectionnode listnode heada,listnode headb listno...
回顧資料結構與演算法1
資料結構 儲存資料的不同方式 演算法 同一問題不同的解決方法 陣列 演算法 每次插入需分配新空間 插入慢 查詢快 鍊錶 演算法 每次插入指標指向即可 插入快 查詢慢 如何選擇演算法 大o表示法 1 時間測算 時間複雜度 big o long before system.currenttimemull...