数据结构 链表

目录

 

● 请你说出几种基本的数据结构,

参考回答:

● 手写代码:怎么判断链表有环,怎么找环节点

参考回答:

● 手写代码:一个单向链表,给出头结点,找出倒数第N个结点,要求O(N)的时间复杂度;

参考回答:

● 请问如何判断一个单向链表存在回路?

参考回答:

● 请问如何判断一个链表是否有环

参考回答:

● 请问如何判断两个链表是否相交

参考回答:

● 手写代码:循环链表插入元素

参考回答:


● 请你说出几种基本的数据结构,

参考回答:

常见的基本的数据结构有链表、栈、队列、树(只列出面试常考的基本数据结构)

1、链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列节点组成,这些节点不必在内存中相连。每个节点由数据部分Data和链部分Next,Next指向下一个节点,这样当添加或者删除时,只需要改变相关节点的Next的指向,效率很高。

栈和队列是比较特殊的线性表

栈是限制插入和删除只能在一个位置上进行的表,后进先出

队列只允许在front端进行删除操作,在rear端进行插入操作,

树:树型结构是一类非常重要的非线性数据结构,考察主要以二叉树为主,

● 手写代码:怎么判断链表有环,怎么找环节点

参考回答:

判断是否有环以及环节点

public class Solution {

ListNode EntryNodeOfLoop(ListNode h){

if(h == null || h.next == null)

return null;

ListNode slow = h;

ListNode fast = h;

while(fast != null && fast.next != null ){

slow = slow.next;

fast = fast.next.next;

if(slow == fast){

ListNode p=h;

ListNode q=slow;//相当于让q指向了m1

while(p != q){

p = p.next;

q = q.next;

}

if(p == q)

return q;

}

}

return null;

}

● 手写代码:一个单向链表,给出头结点,找出倒数第N个结点,要求O(N)的时间复杂度;

参考回答:

JAVA版本:

public class Solution {

public ListNode FindNthToTail(ListNode head,int N) {

ListNode pre=null,p=null;

//两个指针都指向头结点

p=head;

pre=head;

//记录N值

int a=N;

//记录节点的个数

int count=0;

//p指针先跑,并且记录节点数,当p指针跑了N-1个节点后,pre指针开始跑,

//当p指针跑到最后时,pre所指指针就是倒数第N个节点

while(p!=null){

p=p.next;

count++;

if(N<1){

pre=pre.next;

}

N--;

}

//如果节点个数小于所求的倒数第N个节点,则返回空

if(count<a) return null;

return pre;

}

}

C/C++版本:

class Solution {

public:

ListNode* FindNthToTail(ListNode* pListHead, unsigned int N) {

if(pListHead==NULL||N==0)

return NULL;

ListNode*pTail=pListHead,*pHead=pListHead;

for(int i=1;i<N;++i)

{

if(pHead->next!=NULL)

pHead=pHead->next;

else

return NULL;

}

while(pHead->next!=NULL)

{

pHead=pHead->next;

pTail=pTail->next;

}

return pTail;

}

};

Python:

class Solution:

def FindNthToTail(self, head, N):

# write code here

res=[]

while head:

res.append(head)

head=head.next

if N>len(res) or N<1:

return

return res[-N]

● 请问如何判断一个单向链表存在回路?

参考回答:

方法1:用一个指针数组A,存储已访问过的节点。用一个指针p,每次在链表上移动一步,然后与指针数组A比较,若数组中没有指针与p相同,说明第一次访问p,将p放入数组中;若有指针与p相同,则存在环路,且第一次相同的节点就是环的入口点。

链表长度为n,则需要空间o(n),且每次要与指针数组比较,时间复杂度为 O(n^2)。

方法2:在节点上记录该节点是否被访问过,如果在指针移动过程中遇到已访问过的节点,说明存在环路。同样地,第一次相同的节点就是环的入口点。

方法3:用两个指针,pSlow,pFast,一个慢一个快,慢的一次跳一步,,快的一次跳两步,如果快的能追上慢的就表示有环(pSlow == pFast )。

● 请问如何判断一个链表是否有环

参考回答:

方法1:用一个指针数组A,存储已访问过的节点。用一个指针p,每次在链表上移动一步,然后与指针数组A比较,若数组中没有指针与p相同,说明第一次访问p,将p放入数组中;若有指针与p相同,则存在环路,且第一次相同的节点就是环的入口点。

链表长度为n,则需要空间o(n),且每次要与指针数组比较,时间复杂度为 O(n^2)。

方法2:在节点上记录该节点是否被访问过,如果在指针移动过程中遇到已访问过的节点,说明存在环路。同样地,第一次相同的节点就是环的入口点。

方法3:用两个指针,pSlow,pFast,一个慢一个快,慢的一次跳一步,,快的一次跳两步,如果快的能追上慢的就表示有环(pSlow == pFast )。

● 请问如何判断两个链表是否相交

参考回答:

从头遍历两个链表。创建两个栈,第一个栈存储第一个链表的节点,第二个栈存储第二个链表的节点。每遍历到一个节点时,就将该节点入栈。两个链表都入栈结束后。则通过top判断栈顶的节点是否相等即可判断两个单链表是否相交。因为我们知道,若两个链表相交,则从第一个相交节点开始,后面的节点都相交。 若两链表相交,则循环出栈,直到遇到两个出栈的节点不相同,则这个节点的后一个节点就是第一个相交的节点。

node temp=NULL; //存第一个相交节点

while(!stack1.empty()&&!stack1.empty()) //两栈不为空

{

temp=stack1.top();

stack1.pop();

stack2.pop();

if(stack1.top()!=stack2.top())

{

break;

}

}

● 手写代码:循环链表插入元素

参考回答:

typedef struct _tag_CircleListNode

{

struct _tag_CircleListNode * next;

}CircleListNode;

typedef struct _tag_CircleList

{

CircleListNode header;

CircleListNode* slider;

int length;

}TCircleList;

//插入元素

int CircleList_insert(CircleList* list, CireListNode* node, int pos)

{

int ret = 0, i=0;

TCircleList* sList = (TCircleList*)list;

if (list == NULL || node== NULL || pos<0)

{

return -1;

}

CircleListNode* current = (CircleListNode*)sList;

for(i=0; (i<pos) && (current->next != NULL); i++)

{

current = current->next;

}

//current->next 0号节点的地址

node->next = current->next; //1

current->next = node; //2

//若第一次插入节点

if( sList->length == 0 )

{

sList->slider = node;

}

sList->length++;

//若头插法 current仍然指向头部

//(原因是:跳0步,没有跳走) 中间第一种情况

if( current == (CircleListNode*)sList )

{

//获取最后一个元素

CircleListNode* last = CircleList_Get(sList, sList->length - 1);

last->next = current->next; //3

}

return ret;

}

CircleListNode* CircleList_Get(CircleList* list, int pos) // O(n)

{

TCircleList* sList = (TCircleList*)list;

CircleListNode* ret = NULL;

int i = 0;

if (list==NULL || pos<0)

{

return NULL;

}

{

CircleListNode* current = (CircleListNode*)sList;

for(i=0; i<pos; i++)

{

current = current->next;

}

ret = current->next;

}

return ret;

}

猜你喜欢

转载自blog.csdn.net/u012369559/article/details/89494420