文章目錄
1.從尾到頭打印鏈表
輸入一個鏈表,按鏈表從尾到頭的順序返回一個ArrayList。
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> res;
if(!head)
return res;
while(head!=nullptr){
res.push_back(head->val);
head = head->next;
}
reverse(res.begin(),res.end());
return res;
}
注意:此處重點應當是考查棧的使用,不過先輸入在反轉也可以,時間複雜度一樣。
2.鏈表中倒數第k個結點
輸入一個鏈表,輸出該鏈表中倒數第k個結點。
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(pListHead==nullptr || k<=0)
return nullptr;
ListNode* fast=pListHead, *slow=pListHead;
unsigned int i=k;
for(;i>0&&fast;--i)
fast = fast->next;
if(i!=0) return nullptr;
while(fast){
fast = fast->next;
slow = slow->next;
}
return slow;
}
};
3.反轉鏈表
輸入一個鏈表,反轉鏈表後,輸出新鏈表的表頭。
ListNode* ReverseList(ListNode* pHead) {
if(pHead==nullptr||pHead->next==nullptr)
return pHead;
ListNode *pre=pHead, *now=pHead->next, *tmp=nullptr;
pre->next = nullptr;
while(now){
tmp = now;
now = now->next;
tmp->next = pre;
pre = tmp;
}
return pre;
}
4. 合併兩個排序的鏈表
輸入兩個單調遞增的鏈表,輸出兩個鏈表合成後的鏈表,當然我們需要合成後的鏈表滿足單調不減規則。
class Solution {
public:
void merge(ListNode* p1, ListNode* p2,ListNode* head){
ListNode* to=head;
while(p1&&p2){
if(p1->val<=p2->val){
to->next = p1;
to = to->next;
p1 = p1->next;
}else{
to->next = p2;
to = to->next;
p2 = p2->next;
}
}
while(p1){
to->next = p1;
to = to->next;
p1 = p1->next;
}
while(p2){
to->next = p2;
to = to->next;
p2 = p2->next;
}
to->next = nullptr;
}
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(!pHead1)
return pHead2;
else if(!pHead2)
return pHead1;
ListNode *p1=pHead1, *p2=pHead2, *head;
if(p1->val<=p2->val){
head = p1;
merge(p1->next,p2,head);
}else{
head = p2;
merge(p1,p2->next,head);
}
return head;
}
};
5.複雜鏈表的複製
輸入一個複雜鏈表(每個節點中有節點值,以及兩個指針,一個指向下一個節點,另一個特殊指針指向任意一個節點),返回結果爲複製後複雜鏈表的head。(注意,輸出結果中請不要返回參數中的節點引用,否則判題程序會直接返回空)
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
RandomListNode* CopyNode(RandomListNode* node){
RandomListNode* head = new RandomListNode(node->label);
head->next = node->next;
return head;
}
RandomListNode* Clone(RandomListNode* pHead){
if(!pHead) return nullptr;
RandomListNode* node = pHead, *clone=nullptr;
while(node){//複製單個節點
node->next = CopyNode(node);
node = node->next->next;
}
node = pHead;
while(node){//複製random節點
if(node->random)
node->next->random = node->random->next;
node = node->next->next;
}
RandomListNode* head = pHead->next;
node=pHead;
node->next = head->next;
node = node->next;
clone = head;
while(node){//分離複合鏈表
clone->next = node->next;
clone = clone->next;
node->next = clone->next;
node = node->next;
}
return head;
}
};
6. 二叉搜索樹與雙向鏈表
輸入一棵二叉搜索樹,將該二叉搜索樹轉換成一個排序的雙向鏈表。要求不能創建任何新的結點,只能調整樹中結點指針的指向。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
void ConvertNode(TreeNode* proot,TreeNode** plast){
if(!proot)
return;
ConvertNode(proot->left,plast);
proot->left = *plast;
if((*plast))
(*plast)->right = proot;
*plast = proot;
ConvertNode(proot->right,plast);
}
TreeNode* Convert(TreeNode* pRootOfTree)
{
TreeNode *plastnode = nullptr;
ConvertNode(pRootOfTree,&plastnode);
TreeNode* head = plastnode;
while(head!=nullptr && head->left!=nullptr)
head = head->left;
return head;
}
};
7. 兩個鏈表的第一個公共結點
輸入兩個鏈表,找出它們的第一個公共結點。(單鏈表)
class Solution {
public:
void length(ListNode* pHead1, ListNode* pHead2 ,int *l1, int *l2){
(*l1)=(*l2)=0;
while(pHead1)
{ pHead1 = pHead1->next; ++(*l1);}
while(pHead2)
{ pHead2 = pHead2->next; ++(*l2);}
}
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
if(!pHead1 || !pHead2)
return nullptr;
ListNode *pub, *p1=pHead1,*p2=pHead2;
int l1,l2;
length(p1,p2,&l1,&l2);
int tmp =(l1>l2)?(l1-l2):(l2-l1);
while(tmp--){
if(l1>l2)
p1 = p1->next;
else
p2 = p2->next;
}
while(p1!=p2){
p1 = p1->next;
p2 = p2->next;
}
return p1;
}
};
8.鏈表中環的入口結點(單鏈表)
給一個鏈表,若其中包含環,請找出該鏈表的環的入口結點,否則,輸出null。
class Solution {
public:
bool HasCircle(ListNode* phead,ListNode** meet){
if(phead==nullptr || phead->next==nullptr)
return false;
ListNode *slow=phead->next;
ListNode *fast=slow->next;
while(fast&&slow && fast!=slow){
if(fast->next)
fast = fast->next->next;
else
break;
slow = slow->next;
}
(fast==slow)?((*meet)=fast):((*meet)=nullptr);
return (fast==slow);
}
int NumberofCircle(ListNode* phead){
ListNode *meet, *p;
int num=1;
if(!HasCircle(phead,&meet))
return -1;
p = meet->next;
while(p!=meet){
++num;
p = p->next;
}
return num;
}
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
int nums ;
if((nums=NumberofCircle(pHead))==-1)
return nullptr;
ListNode *front=pHead, *rear=pHead;
while(nums--)
front = front->next;
while(front != rear){
front = front->next;
rear = rear->next;
}
return front;
}
};
9. 刪除鏈表中重複的結點
在一個排序的鏈表中,存在重複的結點,請刪除該鏈表中重複的結點,重複的結點不保留,返回鏈表頭指針。 例如,鏈表1->2->3->3->4->4->5 處理後爲 1->2->5
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead)
{
if(pHead==nullptr || pHead->next==nullptr)
return pHead;
ListNode* preNode = nullptr;
ListNode* pNode = pHead;
while(pNode!=nullptr){
ListNode* next = pNode->next;
bool needDelete = false;
if(next && next->val==pNode->val)
needDelete = true;
if(!needDelete){
preNode = pNode;
pNode = next;
}else{
int val = pNode->val;
ListNode* delNode = pNode;
while(delNode!=nullptr && delNode->val==val){
next = delNode->next;
delete delNode;
delNode = next;
}
if(preNode==nullptr)
pHead = next;
else
preNode->next = next;
pNode = next;
}
}
return pHead;
}
};
10. 數值的整數次方
給定一個double類型的浮點數base和int類型的整數exponent。求base的exponent次方。
保證base和exponent不同時爲0(要考慮全面)
class Solution {
public:
double PowerWithexp(double base,int absexp){
if(absexp==0)
return 1;
if(absexp==1)
return base;
double res = PowerWithexp(base,absexp>>1);
res *=res;
if(absexp&0x1==1)
res *=base;
return res;
}
double Power(double base, int exponent) {
if(base==0 && exponent<0 || base==0)
return 0;
int absexp;
(exponent>=0)?(absexp=exponent):(absexp=-exponent);
double res = PowerWithexp(base,absexp);
if(exponent<0)
res = 1.0/res;
return res;
}
};