01 认识『链表』
链表的结构十分简单,其本身是一种线性的存储结构,通过物理地址不连续的节点相连接成链。最简单的单链表只包含一条链,并且每一个节点包括两部分内容,数据元素和下一个节点的地址。因此可通过已知节点访问它的下一个节点。
相比于数组而言,由于链表不必须按顺序存储,因而在插入的时候可以达到O(1)的复杂度,一般而言比数组的效率要高得多;但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而数组由于可以直接通过下标寻址,相应的时间复杂度仅为O(1)。
一般可通过定义结构体的方式来实现链表:
// Definition for singly-linked list.
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {
}
};
02 高频算法题
1. 输入一个链表,输出该链表中倒数第k个结点。
快慢指针的方法在链表相关的操作中经常使用。
通过设置快慢指针,快指针先前进k步,之后快慢指针同时前进,此时快慢指针间隔k步;当快指针到达链表尾部,此时慢指针所在节点即为倒数第k个节点。这样的方法仅通过一次遍历即可获得倒数第k个节点。
代码如下:
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(pListHead==NULL||k==0)
return NULL;
ListNode*pTail=pListHead,*pHead=pListHead;
for(int i=1;i<k;++i)
{
if(pHead->next!=NULL)
pHead=pHead->next;
else
return NULL;
}
while(pHead->next!=NULL)
{
pHead=pHead->next