链表中倒数第k个结点
题目描述
输入一个链表,输出该链表中倒数第k个结点。
实现思路
比较直接的办法就是用一指针先遍历整个链表,求得链表长度并减去k,就能知道所求的结点为正数第几个了。然后再用另一指针从头出发遍历即可到达。
还有一种做法是利用栈先进后出的规则,跟倒数是一个意思。依次将结点从头到尾压入栈中,最后弹出k次就能得到。
还有一个办法是利用双指针,先让一指针走k-1步,到达第k个结点,还剩len-k个结点。此时另一指针从头出发,两个指针一起走直到刚开始的指针到达链表尾部时,后出发的指针刚好到正数第len-k+1个结点,即为倒数第k个结点。
具体实现
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(pListHead==NULL||k==0)
return NULL;
ListNode* pHead = pListHead ;
ListNode* pPre = pListHead;
int count=k-1;
while(count--){
pHead=pHead->next;
}
if(pHead==NULL)
return NULL;
while(pHead->next!=NULL){
pHead=pHead->next;
pPre=pPre->next;
}
return pPre;
}
};
反转链表
题目描述
输入一个链表,反转链表后,输出新链表的表头。
实现思路
反转链表的思路其实就是一个指针往后遍历链表,让下一个结点指向自己,但是要注意为了不丢失后面的结点,保证指针正确往后遍历,还需要一个指针来保存后面结果。
总结起来就是,一个指针实现反转操作,最后成为反转链表的头节点,另一指针维护这个遍历过程。
具体实现
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead==NULL||pHead->next==NULL)
return pHead;
ListNode* curList = pHead;
ListNode* newList = NULL;
while(curList!=NULL){
ListNode* next = curList->next;
curList->next = newList;
newList = curList;
curList = next;
}
return newList;
}
};
合并两个排序的链表
题目描述
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
实现思路
还是,还是,还是要用到两个指针!做链表的题目最怕的就是遍历着遍历着然后链表丢了。
这个题目其实很明了了,首先定义一个答案指针要用来指向较小数的链表头部,方便最后返回。然后不断往后遍历两个链表并比较大小,用另一指针往后存储较小数即可。
具体实现
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1==NULL)
return pHead2;
if(pHead2==NULL)
return pHead1;
ListNode* res = NULL;
ListNode* cur = NULL;
while(pHead1!=NULL&&pHead2!=NULL){
if(pHead1->val <= pHead2->val){
if(res==NULL){
cur=pHead1;
res=cur;
}
else{
cur->next=pHead1;
cur=cur->next;
}
pHead1=pHead1->next;
}
else {
if(res==NULL){
cur=pHead2;
res=cur;
}
else{
cur->next=pHead2;
cur=cur->next;
}
pHead2=pHead2->next;
}
}
if(pHead1==NULL)
cur->next=pHead2;
else
cur->next=pHead1;
return res;
}
};
树的子结构
题目描述
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
实现思路
看到别人写的一个递归版本真的太厉害了,简单易懂。就是不断地将A的子结点的子树与B做比较,如果B的结点都比较完了还没报错则返回正确;如果A的结点都比较完了还没返回正确,说明B不可能是A的子树,则返回错误。
具体实现
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
if(pRoot1==NULL||pRoot2==NULL)
return false;
return isSubtree(pRoot1,pRoot2)
||HasSubtree(pRoot1->left, pRoot2)
||HasSubtree(pRoot1->right, pRoot2);
}
bool isSubtree(TreeNode* pRoot1, TreeNode* pRoot2){
if(pRoot2==NULL)
return true;
if(pRoot1==NULL)
return false;
return pRoot1->val==pRoot2->val
&&isSubtree(pRoot1->left,pRoot2->left)
&&isSubtree(pRoot1->right,pRoot2->right);
}
};