牛客劍指offer刷題記錄(五)

2021-09-30 13:41:48 字數 3350 閱讀 4753

鍊錶的指標域中,除了有指向下乙個節點的鍊錶以外,還有乙個指向隨機節點的指標。

struct listnode

;

常規做法,空間換時間。

先常規的將拷貝的節點用next串起來,遍歷一遍原始鍊錶,然後尾插法即可。

在尾插的同時,建立乙個由原始節點指標p到拷貝節點指標c的乙個map。

再次遍歷原始指標,如果指標p指向節點的random域不為null,那麼通過m[p]->random=m[p->random]來達到賦值random的目的:

class solution 

tail->next = nullptr;

p = phead;

while (nullptr != p)

p = p->next;

}return newhead->next;

}};

相當聰明的做法,看了書才能知道,就是把clone的節點接到原節點的後面

例如:

l1->l2->l3

變成 l1->l1』->l2->l2』->l3->l3』->null

然後有p->next->random=p->random->next

最後再把這個鍊錶拆成兩個鍊錶即可。

class solution 

p = phead;

while (nullptr != p)

p = p->next->next;

}randomlistnode * newhead = new randomlistnode(0);//新鍊錶的頭結點

randomlistnode *k = newhead;

randomlistnode* o = phead;//這裡還需要保證原鍊錶的形狀

p = phead->next;

while (nullptr != p)

return newhead->next;

}};

將二叉搜尋樹轉成雙向鍊錶:

原先指向左子樹的指標調整為指向雙向鍊錶中前乙個節點的的指標pre,原先指向右子樹的指標調整為指向雙向鍊錶後乙個節點的指標next.

由於二叉搜尋樹中序遍歷的序列是有序的,而題目要求雙向鍊錶也是有序的,因此,我們以中序的方式進行遞迴。

這裡,我們還需要乙個輔助的指標,指向當前已經排好的雙向鍊錶的最後乙個節點。

所以,遞迴的順序是,先排左子樹,再排當前節點,再排右子樹。

排好以後,list指標需要往回溯,找到雙向鍊錶的頭結點。

class solution 

public:

treenode* convert(treenode* prootoftree)

return

list;

}};

把字串分成兩部分,一部分是字串的第乙個字元,一部分是第乙個字元後面所有的字元,將第乙個字元分別與後面所有的字元交換:

比如abc,a與b、c分別交換,得到序列bac和cba。

對於子串行,再遞迴地完成該操作即可。

不過牛客上面有個兩個要求:

1.要求字串出現重複字元,即可能有aac這樣的序列

2.要求字串是字典序的。

對於第2個要求,我們很容易實現,只要將第乙個字元後面所有的字元sort一下即可,對於第1個要求,如果出現重複字元,則不執行swap操作,這裡需要維護乙個visit容器。

class solution 

sort(str.begin() + start, str.end());//保證字典序

unordered_set

visit;//保證重複不交換

for (int i = start; i < str.size(); ++i)}}

public:

vector

permutation(string str)

};

詳細參考:leetcode169—majorityelements

class solution 

else

}//下面**排除沒有多數派情況

count = 0;

for (int i = 0; iif (numbers[i] == candidates)

count++;

}if (count <= (numbers.size() ) / 2)

return

0; return candidates;

}};

借助容器了。

能想象到,最小的k個數和最大的k個數可以用堆這種結構來儲存。這裡我用乙個優先順序佇列。事實上紅黑樹也是可以的,用乙個set也是可以的。

class solution 

vector

v;v.reserve(q.size());

while (!q.empty())

reverse(v.begin(), v.end());

return v;

}};

class solution 

}vector

v;v.reserve(s.size());

for (auto it = s.begin(); it != s.end(); ++it)

return v;

}};

第二種思路是用partition函式來解決問題,可以想見,快排的思路是比基準小的在左邊,比基準pivot大的再右邊,先回顧一下快排和partition函式。

int partition(vector

&v, int p, int r)

}swap(v[r], v[i+1]);

return i +1;

}void quicksort(vector

&v, int p, int r)

}

如果基於陣列的第k個數字來調整,使得比第k個數字小的在陣列左邊,比第k個數字大的都在右邊,這樣左邊的k個數字就是k個最小數字。基於這種思路的**如下:

int partition(vector

&v, int p, int r)

}swap(v[r], v[i+1]);

return i +1;

}class solution

else

}//end while

vector

res(input.begin(), input.begin() + k);

return res;

}};

牛客劍指offer刷題記錄(七)

演算法導論上應該有這樣的課後題。歸併的思路,假設f i,j 表示陣列i到j的逆序對數,那麼有 f i,j f i k f k 1,j s i j,k 其中s i,j,k 表示逆序對 p q p i k q k 1,j 由於歸併排序,我麼得到兩個有序的子陣列l,r 那麼當出現逆序對 l i r j 時...

牛客網劍指offer刷題記錄(更新ing)

1.二維陣列的查詢 class solution else else 索引 1 index new index 3.從尾到頭列印鍊錶 struct listnode class solution while array tmp.size 0 return array result 4.重建二叉樹 d...

劍指 offer 刷題記錄

任誰都躲不過找工作的問題,好希望能多準備一些時間,奈何時間不等人,每天刷幾道題,並且記錄下來吧 def replacespace s write code here num space 0 new s for i in range len s if i num space 1 for i in ra...