版权声明: https://blog.csdn.net/qq_41880190/article/details/85110546
1、查找倒数第 k 个链表
题目描述:给定一个单向链表 List ,要你设计算法找出倒数第 K 个结点并打印
struct ListNode
{
DataType m_Value;
ListNode* m_pNext;
};
ListNode* FindKthToTail(ListNode* pHead);
首先我自己的思路:
1、首先我们能想到的是假如给定的是一个双向链表就好了,我们可以从链表的尾部向前遍历找到倒数第 K 个结点,但是对于我们这道题显然是行不通的
2、根据链表的特性我们能想到的是,链表节点数假设为 n ,要找倒数第 K 个结点,则我们只需从前往后遍历链表,走 (n - k + 1) 步就可以得到倒数第 K 个结点;至于链表总结点数,我们可以遍历链表得出::为了实现只遍历一次链表就得到倒数第 K 个结点,我们可以定义两个指针第一个指针从头节点遍历走 (k - 1) 步,从第 K 步开始两个指针同步向后遍历,当快指针到达链表的尾节点是,慢指针刚好是倒数第 K 个结点;基于这种思路我们可以写出简单的代码;如下:
#include "SList.h"
/*
* struct ListNode
{
DataType m_Value;
ListNode* m_pNext;
};
*/
ListNode* FindKthToTail(ListNode* pHead, unsigned int k)
{
if(pHead == nullptr || k == 0)
return nullptr;
ListNode* pFast = pHead;
ListNode* pSlow = pHead;
while(--k && pFast->m_pNext != nullptr)
pFast = pFast->m_pNext;
while(pFast->m_pNext != nullptr)
{
pFast = pFast->m_pNext;
pSlow = pSlow->m_pNext;
}
cout << pSlow->m_Value << endl;
return pSlow;
}
void FindKthToTailTest()
{
cout << ">>查找链表倒数第 K 个结点" << endl;
ListNode* pHead;
SListInit(&pHead);
SListPushBack(&pHead, 1);
SListPushBack(&pHead, 2);
SListPushBack(&pHead, 4);
SListPushBack(&pHead, 7);
SListPushBack(&pHead, 3);
SListPushBack(&pHead, 5);
SListPushBack(&pHead, 9);
SListPushBack(&pHead, 8);
SListPushBack(&pHead, 12);
cout << "倒数第 3 个结点 : " << FindKthToTail(pHead, 3) << endl;
SListPrint(pHead);
}
int main()
{
FindKthToTailTest();
return 0;
}
运行结果:
解答这道题需注意的是:
1、输入的链表为空
2、链表总结点数少于 K 或者链表的总结点数 K== 0
优化后的代码为:
#include "SList.h"
/*
* struct ListNode
{
DataType m_Value;
ListNode* m_pNext;
};
*/
ListNode* __FindKthToTail(ListNode* pHead, unsigned int k)
{
if(pHead == nullptr || k == 0)
return nullptr;
ListNode* pFast = pHead;
ListNode* pSlow = pHead;
for(unsigned int i = 0; i < k-1; ++i)
{
if(pFast->m_pNext != nullptr)
{
pFast = pFast->m_pNext;
}
else
{
return nullptr;
}
}
while(pFast->m_pNext != nullptr)
{
pSlow = pSlow->m_pNext;
}
return pSlow;
}
void __FindKthToTailTest()
{
cout << ">>优化版本:" << endl;
cout << ">>查找链表倒数第 K 个结点:" << endl;
ListNode* pHead;
SListInit(&pHead);
SListPushBack(&pHead, 1);
SListPushBack(&pHead, 2);
SListPushBack(&pHead, 4);
SListPushBack(&pHead, 7);
SListPushBack(&pHead, 3);
SListPushBack(&pHead, 5);
SListPushBack(&pHead, 9);
SListPushBack(&pHead, 8);
SListPushBack(&pHead, 12);
cout << "倒数第 3 个结点 : " << __FindKthToTail(pHead, 3) << endl;
SListPrint(pHead);
}
int main()
{
//FindKthToTailTest();
__FindKthToTailTest();
return 0;
}
#include "SList.h"
/*
* struct ListNode
{
DataType m_Value;
ListNode* m_pNext;
};
*/
ListNode* __FindKthToTail(ListNode* pHead, unsigned int k)
{
if(pHead == nullptr || k == 0)
return nullptr;
ListNode* pFast = pHead;
ListNode* pSlow = pHead;
for(unsigned int i = 0; i < k-1; ++i)
{
if(pFast->m_pNext != nullptr)
{
pFast = pFast->m_pNext;
}
else
{
return nullptr;
}
}
while(pFast->m_pNext != nullptr)
{
pSlow = pSlow->m_pNext;
}
return pSlow;
}
void __FindKthToTailTest()
{
cout << ">>优化版本:" << endl;
cout << ">>查找链表倒数第 K 个结点:" << endl;
ListNode* pHead;
SListInit(&pHead);
SListPushBack(&pHead, 1);
SListPushBack(&pHead, 2);
SListPushBack(&pHead, 4);
SListPushBack(&pHead, 7);
SListPushBack(&pHead, 3);
SListPushBack(&pHead, 5);
SListPushBack(&pHead, 9);
SListPushBack(&pHead, 8);
SListPushBack(&pHead, 12);
cout << "倒数第 3 个结点 : " << __FindKthToTail(pHead, 3) << endl;
SListPrint(pHead);
}
int main()
{
//FindKthToTailTest();
__FindKthToTailTest();
return 0;
}
2、反转链表
扫描二维码关注公众号,回复:
4671822 查看本文章
ListNode* ReverseList(ListNode* pHead)
{
if(pHead == NULL)
{
return NULL;
}
if(pHead->next == NULL)
{
return pHead;
}
ListNode* pCur = pHead->next;
ListNode* pPrev = pHead;
ListNode* pNext = pCur->next;
while(pCur->next)
{
pNext = pCur->next;
pCur->next = pPrev;
pPrev = pCur;
pCur = pNext;
}
pCur->next = pPrev;
//最后一个节点的指向它的前驱
pHead->next = NULL;
//最后一个结点的下一个结点置 NULL
return pCur;
}
栈实现
ListNode* ReverseList(ListNode* pHead)
{
if (pHead == nullptr || pHead->next == nullptr)
{
return pHead;
}
stack<ListNode*> node;
ListNode* pCur = pHead;
while(pCur->next) //链表不为空入栈
{
node.push(pCur);
pCur = pCur->next;
}
ListNode* pReversedNode = pCur; //反转后新链表的头节点就是栈顶元素
while(!node.empty())
{
pCur->next = node.top();
pCur = pCur->next;
node.pop();
}
pCur->next = NULL;
return pReversedNode;
}
递归实现
ListNode* ReverseList(ListNode* pHead)
{
if(pHead == NULL || pHead->next == NULL)
return pHead;
ListNode* pReversedNode = ReverseList(pHead->next);
pHead->next->next = pHead; //反转节点
phead = NULL; //第一个节点反转后置下一个为 NULL
return pReversedNode;
}
从尾到头打印链表
递归实现
void ReverseList(ListNode* pHead)
{
if(pHead != NULL)
{
if(pHead->next != NULL)
{
ListNode* pReversedNode = ReverseList(pHead->next);
}
cout << pReversedNode->data;
}
}
栈实现
j仅仅打印链表的值,不修改链表结构
先遍历链表,再打印
void ReverseList(ListNode* pHead) //先进后出利用栈的特性
{
if(pHead == NULL || pHead->next == NULL);
return phead;
stack<ListNode*> node;
ListNode* pCur = pHead;
while(pCur->next) //pCur 一直遍历直到 pCur->next == NULL,入栈结束
{
node.push(pCur);
pCur = pCur->next;
}
while(!node.empty()) //栈不为空,pop 出栈并且打印
{
pCur = node.top();
cout << pCur->data;
node.pop();
}
}
3、找出给定链表的公共结点
题目描述:给定两个链表,找出它们的第一个公共节点::分三步
1、分别计算两个链表的长度
2、比较出较长的那一个链表,长出多少,较长的链表从头开始向后遍历多少步
3、找公共节点(找第一个公共结点、ps:找出现的公共结点)
代码如下:SList.h
/*************************************************************************
> File Name: SList.h
> Author:
> Mail:
> Created Time: Tue Oct 23 20:19:58 2018
************************************************************************/
#pragma once
#include <iostream>
using namespace std;
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int DataType;
//节点结构体
typedef struct ListNode
{
DataType m_Value;
struct ListNode* m_pNext;
}ListNode;
//查找,找到了返回地址,没有找到返回NULL
ListNode* SListFind(ListNode* p, DataType data)//不改变链表的值,为 ListNode*
{
ListNode* cur = p;
for(cur = p; cur != NULL; cur = cur->m_pNext)
{
if(cur->m_Value == data)
{
return cur;//返回地址
}
}
}
/*
void SListInsert(ListNode* *p,ListNode* pos, DataType m_Value)
{
if(*p == pos)
{
SListPushFront(p, m_Value);
return;
}
ListNode* newNode = CreatNode(m_Value);
ListNode* cur = *p;
while(cur->m_pNext != pos)
{
cur->m_pNext = newNode;
newNode->m_pNext = pos;
cur = cur->m_pNext;
}
}
*/
void SListInit(ListNode* *p)
{
assert(p != NULL);
*p = NULL;
}
void SListDestroy(ListNode* *p)
{
assert(p != NULL);
}
static ListNode* CreatNode(DataType m_Value)
{
ListNode* pNode = (ListNode *)malloc(sizeof(ListNode));
pNode->m_Value = m_Value;
pNode->m_pNext = NULL;
return pNode;
}
//尾删
void SListPopBack(ListNode* *p)
{
assert(p != NULL);
assert(*p != NULL);//判断链表是否为空
if((*p)->m_pNext == NULL)
{
free(p);
p = NULL;
return ;
}
//链表中至少有两个
ListNode* cur = *p;
while(cur->m_pNext != NULL)
{
//free(cur->m_pNext);
cur = cur->m_pNext;
}
free(cur->m_pNext);
cur->m_pNext = NULL;
}
//头删
//尾插
void SListPushBack(ListNode* *p, DataType m_Value)
{
ListNode* pNode = CreatNode(m_Value);/* 申请节点,赋值且插入 */
assert(p != NULL);//传入地址不为空
if(*p == NULL)/* 链表为空 */
{
*p = pNode;
return ;
}
//找链表中的最后一个节点
//ListNode* pNode = CreatNode(m_Value);//申请节点,赋值且插入
ListNode* cur = *p;
while(cur->m_pNext != NULL)
{
cur = cur->m_pNext;
}
cur->m_pNext = pNode;
}
//头插
void SListPushFront(ListNode* *p, DataType m_Value)
{
assert(p != NULL);
//assert(*p != NULL);
ListNode* pNode = (ListNode *)malloc(sizeof(ListNode));
pNode->m_Value = m_Value;
pNode->m_pNext = NULL;
//pNode->m_pNext = *p;
*p = pNode;
}
void SListPrint(ListNode* p)
{
ListNode* cur = p;
while(cur != NULL)
{
printf("%d ", cur->m_Value);
cur = cur->m_pNext;
}
printf("\n");
}
void SListTest()
{
ListNode* pFirst;
SListInit(&pFirst);//初始化
//链表头插
//SListPushFront(&pFirst, 0);
SListPushFront(&pFirst, 1);
SListPushFront(&pFirst, 2);
SListPushFront(&pFirst, 3);
SListPushFront(&pFirst, 4);
SListPushFront(&pFirst, 5);
SListPrint(pFirst);
//链表尾插
SListPushBack(&pFirst, 4);
SListPushBack(&pFirst, 3);
SListPushBack(&pFirst, 2);
SListPushBack(&pFirst, 1);
SListPrint(pFirst);//打印尾插之后的链表
SListPopBack(&pFirst);
SListPopBack(&pFirst);
SListPopBack(&pFirst);
SListPrint(pFirst);
//SListInsert();
//CreatNode(m_Value);
}
ListNode* SList(ListNode* pHead1)
{
//if(pHead == pHead1)
//{
SListInit(&pHead1);
SListPushBack(&pHead1, 0);
SListPushBack(&pHead1, 1);
SListPushBack(&pHead1, 2);
SListPushBack(&pHead1, 3);
SListPushBack(&pHead1, 4);
SListPushBack(&pHead1, 5);
SListPushBack(&pHead1, 6);
SListPushBack(&pHead1, 7);
SListPushBack(&pHead1, 8);
SListPushBack(&pHead1, 9);
//return pHead1;
//}
/*
else
{
ListNode* pHead2;
SListInit(&pHead2);
SListPushFront(&pHead2, 0);
SListPushFront(&pHead2, 1);
SListPushFront(&pHead2, 2);
SListPushFront(&pHead2, 3);
SListPushFront(&pHead2, 4);
SListPushFront(&pHead2, 5);
SListPushFront(&pHead2, 6);
SListPushFront(&pHead2, 7);
SListPushFront(&pHead2, 8);
SListPushFront(&pHead2, 9);
}*/
return pHead1;
}
找公共结点函数:FindSameNode.cpp
/*
struct ListNode {
int data;
struct ListNode *next;
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
if(pHead1 == nullptr || pHead2 == nullptr)
return nullptr;
size_t len1 = 0;
size_t len2 = 0;
ListNode* pCur1 = pHead1;
ListNode* pCur2 = pHead2;
//获取链表长度
while(pCur1)
{
pCur1 = pCur1->next;
len1++;
}
while(pCur2)
{
pCur2 = pCur2->next;
len2++;
}
pCur1 = pHead1;
pCur2 = pHead2;
//比较哪一个链表较长
size_t sublen = 0;
if(len1 < len2)
{
sublen = len2 - len1;
while(sublen--)
pCur2 = pCur2->next;
}
if(len1 > len2)
{
sublen = len1 - len2;
while(sublen--)
pCur1 = pCur1->next;
}
//找公共结点
while(pCur1 != nullptr && pCur2 != nullptr)
{
if(pCur1 == pCur2)
break;
pCur1 = pCur1->next;
pCur2 = pCur2->next;
}
return pCur1;
}
};