今天刷一下题
刷的不多
第一道
链表的回文结构
仔细看这个题它是有限制条件的
首先是时间复杂度和空间复杂度
所以我们并不是用数组去做
但怎么做呢?
思路
既然是判断是否是回文结构,那么我们就找一下他的中间节点
然后将后半段倒置
进行比较
相同返回true
继续想一下
找中间节点的话有两种情况
奇数和偶数
所以我们使用快慢指针的方法去找寻中间节点
但是如果是奇数的话,翻转过来会发现不一样了
但没关系
因为如果是1->2->3->2->1
这样翻转过来就相当于1->2->3-<2-<1
这样是一对一,二对二,而三自己比
代码
#include <cstddef>
class PalindromeList {
public:
//快慢指针
struct ListNode* middleNode(struct ListNode* head) {
ListNode* fast,*slow;
fast=slow=head;
while(fast && fast->next)
{
fast=fast->next->next;
slow=slow->next;
}
return slow;
}
//倒置
struct ListNode* reverseList(struct ListNode* head){
ListNode* n1,*n2,*n3;
n1=NULL;
n2=head;
n3=head->next;
while(n2)
{
n2->next = n1;
//修改三个指针的位置
n1 = n2;
n2 = n3;
if(n3)
{
n3 = n3->next;
}
}
return n1;
}
bool chkPalindrome(ListNode* A) {
// write code here
struct ListNode* mid=middleNode(A);
struct ListNode* rmid = reverseList(mid);
while(mid&&rmid)
{
if(A->val != rmid->val)
return false;
A = A->next;
rmid=rmid->next;
}
return true;
}
};
第二题
思路
第一个思路就是不断地让a链表和b链表的节点进行一一比较
返回相等的交点
时间复杂度是O(N^2)
第二个思路呢就是长链表先把差走完,然后两个链表走后看一看是否节点的next一致,一致就返回该节点
这里对比的是节点不是节点值
代码
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode* curA = headA;
struct ListNode* curB = headB;
int lenA = 1;
while(curA->next)
{
++lenA;
curA = curA->next;
}
int lenB = 1;
while(curB->next)
{
++lenB;
curB = curB->next;
}
if(curA != curB)//不相交
{
return NULL;
}
int gap = abs(lenA - lenB);//abs函数是取绝对值
struct ListNode* longList = headA;
struct ListNode* shortList = headB;
if(lenB > lenA)
{
longList = headB;
shortList = headA;
}
//让长的先走gap步
while(gap--)
{
longList = longList->next;
}
//在同时走,找交点
while(longList != shortList)
{
longList = longList->next;
shortList = shortList->next;
}
return longList;
}
第三题
思路
既然知识点中有双指针
我们就用双指针去做
两个指针,一个快一个慢,快的先走k步
这样到最后快的走完慢的也就到了倒数第k个指针的位置了
返回慢指针就可以了
这个题还是比较简单的
代码
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
// write code here
struct ListNode*fast,*slow;
fast = slow = pListHead;
while(k--)
{
if(fast == NULL)
{
return NULL;
}
fast = fast->next;
}
while(fast)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
第四题
思路
像这个题,麻烦的点是我们不知道他什么时候进环
所以用循环的话很困难
用数组的话我们不知道数组多大也有点麻烦
所以
这道题我们用快慢指针
先确定有环,在确定进环的位置
代码
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode* fast,*slow;
fast = slow = head;
if(head == NULL)
{
return false;
}
while(fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
{
struct ListNode* node1 = head;
struct ListNode* node2 = fast;
while(node1 != node2)
{
node1 = node1->next;
node2 = node2->next;
}
return node2;
}
}
return NULL;
}
第五题
思路
这里我们需要创造节点去拷贝
代码
struct Node* copyRandomList(struct Node* head) {
struct Node* cur = head;
//拷贝节点插入源节点的后面
while(cur)
{
struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
copy->val = cur->val;
//插入
copy->next = cur->next;
cur->next = copy;
//迭代
cur = cur->next->next;
}
//控制拷贝节点的randmo
cur = head;
while(cur)
{
struct Node* copy = cur->next;
if(cur->random == NULL)
{
copy->random = NULL;
}
else
{
copy->random = cur->random->next;
}
//迭代
cur = cur->next->next;
}
//把copy节点解下来,连接成新链表
struct Node* copyhead = NULL,*tail = NULL;
cur = head;
while(cur)
{
struct Node* copy = cur->next;
struct Node* next = copy->next;
//尾插
if(tail == NULL)
{
copyhead = tail = copy;
}
else
{
tail->next = copy;
tail = tail->next;
}
cur->next = next;
cur = next;
}
return copyhead;
}