链表 练习

 

给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。
 
数据范围: 0\leq n\leq10000n1000
要求:空间复杂度 O(1)O(1) ,时间复杂度 O(n)O(n) 。
 
如当输入链表{1,2,3}时,
经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。
/**
 * struct ListNode {
 *  int val;
 *  struct ListNode *next;
 * };
 *
 * C语言声明定义全局变量请加上static,防止重复定义
 */
 
/**
 *
 * @param pHead ListNode类
 * @return ListNode类
 */
struct ListNode* ReverseList(struct ListNode* pHead ) {
    // write code here
    if(pHead == NULL)
    {
        return NULL;
    }
    if(pHead->next == NULL)
    {
        return pHead;
    }
    struct ListNode* p = pHead;
    struct ListNode* pnext = pHead->next;
    p->next = NULL;
    while(pnext)
    {
        struct ListNode* ptmp = pnext->next;
        pnext->next = p;//2->1
        p = pnext;//12--23
        pnext = ptmp;//12--23
    }
    return p;
}

 

将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度 O(n)O(n),空间复杂度 O(1)O(1)。
例如:
给出的链表为 1\to 2 \to 3 \to 4 \to 5 \to NULL12345NULL, m=2,n=4m=2,n=4,
返回 1\to 4\to 3\to 2\to 5\to NULL14325NULL.

数据范围: 链表长度 0 < size \le 10000<size1000,0 < m \le n \le size0<mnsize,链表中每个节点的值满足 |val| \le 1000val1000
 

struct ListNode* reverseBetween(struct ListNode* head, int m, int n ) {
struct ListNode* p = (struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode* p2s;
struct ListNode* plast = NULL;
struct ListNode* p1s;
struct ListNode* pnext;
int i ;
p->next = head;
if(m == n)
{
return head;
}
for(i = 0;i<m;i++)
{
p1s = p;//反转节点的前一个结点
p = p->next;//p在要反转的节点
}
p2s = p;//反转节点 , 成为尾节点

for( i = 0;i<=n-m;i++)
{
pnext = p->next;//存储要滑动的节点
p->next = plast;//反向链接
plast = p;//存储上一节点
p = pnext;//滑动
}
if(p!=NULL)
{
p2s->next = p;//链接新尾部
}

p1s->next = plast;
if(((i == 2)&&(m == 1))||(i == n))//特色case:相邻变化;头尾全变化
{
return plast;
}
return head;
// write code here
}

判断给定的链表中是否有环。如果有环则返回true,否则返回false。

 

bool hasCycle(struct ListNode* head ) {
// write code here
struct ListNode* slow = head;
struct ListNode* fast = head;
while(fast&&fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
{
return true;
}
}
return false;
}

给一个长度为n链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null。
 
数据范围: n\le10000n10000,1<=结点值<=100001<=<=10000

struct ListNode* EntryNodeOfLoop(struct ListNode* pHead ) {
// write code here
struct ListNode* slow = pHead;
struct ListNode* slowtemp;
struct ListNode* fast = pHead;
struct ListNode* find = pHead;
int c = 0;
while(fast&&fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
{
break;
}
}
if((fast == NULL)||(fast->next == NULL))
{
return NULL;
}
slowtemp = slow;
do
{
slow = slow->next;
c++;
}while(slowtemp!= slow);
while(find!=slow)
{
find = find->next;
for(int i =0;i<c;i++)
{
slow = slow->next;
if(slow == find)
{break;}
}
}


return find;
}

 

输入一个长度为 n 的链表,设链表中的元素的值为 ai ,返回该链表中倒数第k个节点。
如果该链表长度小于k,请返回一个长度为 0 的链表。
 

struct ListNode* FindKthToTail(struct ListNode* pHead, int k ) {
// write code here

struct ListNode *plen = pHead,*p = pHead;
int n = 0,j = 0;
while(plen)
{
plen = plen->next;
n++;
}
if(k>n)
{
return NULL;
}
j = n-k;
while(j--)
{
p = p->next;
}
return p;
}

 

给定一个链表,删除链表的倒数第 n 个节点并返回链表的头指针
例如,
给出的链表为: 1\to 2\to 3\to 4\to 512345, n= 2n=2.
删除了链表的倒数第 nn 个节点之后,链表变为1\to 2\to 3\to 51235.
 

struct ListNode *plen = head,*p = head,*plast = NULL;
int len = 0,j = 0;

while(plen)
{
plen = plen->next;
len++;
}
if(len == 1) return NULL;
j = len-n;
if(j>0)
{
while(j--)
{
plast = p;
p = p->next;
}
}
else
{
head = head->next;
}
if((len>2)&&(j!=0))
{
plast->next = p->next;

}
else //len==2的情况
{
if((len - n)==1)
{
head->next = NULL;
}
}
return head;

}

posted @ 2022-05-01 21:59  无头之蝇  阅读(44)  评论(0)    收藏  举报