今天刷一下题
刷的不多
链表的回文结构
仔细看这个题它是有限制条件的
首先是时间复杂度和空间复杂度
所以我们并不是用数组去做
但怎么做呢?
既然是判断是否是回文结构,那么我们就找一下他的中间节点
然后将后半段倒置
进行比较
相同返回true
继续想一下
找中间节点的话有两种情况
奇数和偶数
所以我们使用快慢指针的方法去找寻中间节点
但是如果是奇数的话,翻转过来会发现不一样了
但没关系
因为如果是1->2->3->2->1
这样翻转过来就相当于1->2->3-<2-<1
这样是一对一,二对二,而三自己比
- #include
- 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;
- }