上週面試掛了,反思原因,莫非是因爲一道算法題沒做好嗎?這題目是“判斷兩條鏈表是否交叉,若有交叉,返回交叉節點的指針。” 爲了防止反覆在同一個陰溝裏翻船,決定把最優解寫出來。
#include "pch.h"
#include <iostream>
template<typename T>
class List {
public:
struct Node {
T data;
Node* next;
Node(T& d, Node* ntx = nullptr) : data(d), next(ntx) {}
};
Node* mHead = nullptr;
public:
//List(){}
~List() {
Node* pcur = mHead, *pnext = nullptr;
while (pcur) {
pnext = pcur->next;
delete pcur;
pcur = pnext;
}
}
bool AddNode(T dt, bool attail = true) {
Node*ptr = new Node(dt);
return AddNode(ptr, attail);
}
bool AddNode(Node* nd, bool attail = true) {
if (nd) {
if (attail) {
Node* ptail = Tail();
if (ptail) {
ptail->next = nd;
}
else {
mHead = nd;
}
}
else {
nd->next = mHead;
mHead = nd;
}
return true;
}
return false;
}
Node* Intersect(List& oth) {
Node* lptr = nullptr, *sptr = nullptr;
{
const int sz1 = Size();
const int sz2 = oth.Size();
int num = 0;
if (sz1 >= sz2) {
lptr = mHead;
sptr = oth.mHead;
num = sz1 - sz2;
}
else {
lptr = oth.mHead;
sptr = mHead;
num = sz1 - sz2;
}
for (int i = 0; i < num; ++i) {
if (lptr) {
lptr = lptr->next;
}
}
}
while (lptr && sptr) {
if (lptr == sptr) {
return lptr;
}
lptr = lptr->next;
sptr = sptr->next;
}
return nullptr;
}
private:
Node* Tail() {
Node* ptr = mHead;
while (ptr && ptr->next) {
ptr = ptr->next;
}
return ptr;
}
int Size() {
int sz = 0;
Node* ptr = mHead;
while (ptr) {
++sz;
ptr = ptr->next;
}
return sz;
}
};
int main()
{
std::cout << "Hello World!\n";
List<int> list1, list2;
for (int i = 1; i < 3; ++i) {
list1.AddNode(i);
}
for (int i = 25; i < 28; ++i) {
list2.AddNode(i);
}
#if 1
for (int i = 100; i < 101; ++i) {
List<int>::Node* node = new List<int>::Node(i);
list1.AddNode(node);
list2.AddNode(node);
}
#endif
auto ptr = list1.Intersect(list2);
if (ptr) {
std::cout << "intersect point at " << ptr << std::endl;
}
else {
std::cout << "no intersection\n";
}
return 0;
}
代碼創建了兩條有交叉節點的鏈表。如圖所示:
程序運行結束時,析構這兩條鏈表,發生錯誤,是因爲交叉節點被兩次釋放: