cycle,reverse,rotate linked list
2014-07-17 21:37
253 查看
Linked List Cycle
Given a linked list, determine if it has a cycle in it.
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: bool hasCycle(ListNode *head) { if(head == NULL || head->next == NULL) return false; ListNode* h = head; ListNode* p = head; while(p->next != NULL && p->next->next != NULL)//注意直接是对走两步的进行判断就好,如果结束,两步的先结束, { h = h->next; p = p->next->next; if(p == h) return true; } return false; } };
null.
两个节点,一个快节点(q)每次走两步,一个慢节点(p)每次走一步,如果有环相遇时候,q走得路程是p的两倍
q = x + y + z + y =2p =2(x + y),x起点到环路开始距离,y 环路开始到相遇点距离,z相遇点到环路开始距离
x = z,那么一个点从起点走到环路开始点和一个点从相遇点走到环路开始,都走一步,相遇时候就是环路开始阶段class Solution { public: ListNode *detectCycle(ListNode *head) { if(head == NULL || head->next == NULL) return NULL; ListNode* p = head; ListNode* q = head; bool flag = false; while(q != NULL && q->next != NULL) { q=q->next->next; p=p->next; if(p == q) { p=head; while(p!=q) { p = p->next; q = q->next; } return p; } } return NULL; } };
Reverse Linked List II
Reverse
a linked list from position m to n.
Do it in-place and in one-pass.
主要思想就是边遍历边改变指针,使得在m,n之间的节点指向他们的前一个节点,最后再更改m-1和n+1的指针指向
我翻转链表的方法是往后走,有点复杂,涉及k的判断可能越界
class Solution { public: ListNode *reverseBetween(ListNode *head, int m, int n) { if(head == NULL || m == n) return head; ListNode* guard = new ListNode(0); guard->next = head; ListNode* h = guard; ListNode* p = guard; ListNode* q = guard; ListNode* k = guard; int c = 0; while(c!=m) { ++c; h = p; p = p->next; } q = p->next; k = p->next->next; while(c!=n) { ++c; q->next = p; p = q; q = k; if(k!=NULL) k = k->next; } h->next->next = q; h->next = p; return guard->next; } };
修改的新代码如下
主要在反转的时候,注意添加pre节点,p当前节点,q是下一个节点,这样子迭代就只是当前节点和下一个节点和一个已经处理了的节点,简洁多了。
class Solution { public: ListNode *reverseBetween(ListNode *head, int m, int n) { if(head == NULL || m == n) return head; ListNode* guard = new ListNode(0); guard->next = head; ListNode* h = guard; ListNode* p = guard; ListNode* q = guard; ListNode* pre = NULL; int c = 0; while(c!=m) { ++c; h = p; p = p->next; } while(c<=n) { ++c; q = p->next; p->next = pre; pre = p; p = q; } h->next->next = p; h->next = pre; return guard->next; } };
Reorder List
Givena singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
举个例子,1>2>3>4>5>6>7
——> 1>7>2>6>3>5>4,找到中间点4
1>2>3>4> 1>2>3>4>
>5>6>7 ——> >7>6>5 4之后的节点翻转,然后依次链接到前面的链表中
class Solution { public: void reorderList(ListNode *head) { if(head == NULL || head->next == NULL || head->next->next == NULL) return; ListNode *mid,*p,*q,*k; mid=p=q=k=head; while(p!=NULL && p->next!=NULL) { p = p->next->next; mid = mid->next; } p = mid->next; if(p->next!=NULL) { q = p->next; k = q->next; p->next = NULL; if(k==NULL) { q->next = p; } while(k!=NULL) { q->next = p; p = q; q = k; if(k!=NULL) k = k->next; } if(k==NULL) { q->next = p; } mid->next = q; } p = head; q = mid->next; while(q!=NULL) { mid->next = q->next; q->next = p->next; p->next = q; p = p->next->next; q = mid->next; } } };
下面就个就简单一点,因为他设置了pre,p,q。其中,p是当前节点,q是下一个节点,pre是前一个节点,pre一开始是NULL,这样子,我只需要判断一个节点是否为空就好了,比自己的处理的情况简单。
class Solution { public: void reorderList(ListNode *head) { if(head == NULL || head->next == NULL || head->next->next == NULL) return ; ListNode *mid,*p,*q,*pre=NULL; mid=p=q=head; while(p!=NULL && p->next!=NULL) { p = p->next->next; mid = mid->next; } p = mid->next; if(p->next!=NULL) { while(p!=NULL) { q = p->next; p->next = pre; pre = p; p = q; } mid->next = pre; } p = head; q = mid->next; while(q!=NULL) { mid->next = q->next; q->next = p->next; p->next = q; p = p->next->next; q = mid->next; } } };
Rotate List
Given a list, rotate the list to the right by k places, where k is non-negative.
For example:
Given
1->2->3->4->5->NULLand k =
2,
return
4->5->1->2->3->NULL.
class Solution { public: ListNode *rotateRight(ListNode *head, int k) { //完全理解错题目的意思,不是找到倒数第k个旋转就好的,此处考虑k是否大于等于链表长度 //而是不断将链表右边的节点向左边旋转k次,k可以无限大,但是可以转化成前面的问题 //规律在于,其实k<length就是前面一个问题,k>length取k % length的值必定小于length即使前面的问题,k==length就是一样的链表 //小心可能k的值比链表长度要大,可能一样长度 if(head == NULL || head->next == NULL || k==0) return head; ListNode *p, *q,*next; next=p=q=head; int c = 1; while(p->next!=NULL)//计算链表长度 { p = p->next; ++c; } k = k % c; if(k==0) return head; p = head; c = 0; while(p!=NULL)//p多走k步 { p = p->next; ++ c; if(c == k) break; } while(p->next!=NULL)//p,q同时走,最后q到达的就是倒数第k个节点的前一个节点,因为我对p->next进行判断,p走到最后一个NULL节点的前一个有 //效节点 { q = q->next; p = p->next; } next = q->next;//第k个节点 q->next = NULL;//倒数第K个节点的前一个节点处断开, p->next = head; return next; } };
Partition List
Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.
You should preserve the original relative order of the nodes in each of the two partitions.
//虽然正确率很高,但是我做了蛮久一是效率低下,一是,太多情况要考虑,有点乱 //首先可能都大于x,或者都小于等于x,还有就是有大于等于也有小于的 //next = cur->next; class Solution { public: ListNode *partition(ListNode *head, int x) { if(head == NULL || head->next == NULL) return head; ListNode* guard = new ListNode(0); guard->next = head; ListNode *cur, *next,*pre; cur = next = guard; //找到第一个大小的分割点,cur if(cur->next->val < x)//首先找到大于等于x的节点的前一个节点,如果第一个就小于x往下找直到到第一个大于等于的节点,如果第一个就大于,不 处理 { while(cur->next!= NULL && cur->next->val < x) cur = cur->next; } pre = cur; next = cur->next; while(next != NULL)//如果是都小于则退出 { if(next->val >= x)//如果都小于等于也退出了,或者是都是大于等于的也退出了,否则,next指向第一个小于的节点,cur是前面小于的最后一个 节点,或者是第一个是大于的前一个guard节点,pre是next的父亲节点 { while(next!= NULL && next->val >= x) { pre = next; next = next->next; } } if(next!=NULL)//加NULL判断,是哪种原因推出while的, {//链接 pre->next = next->next; next->next = cur->next; cur->next = next; cur = cur->next;//注意cur是前面小于的最后一个 节点,需要往后移动一个 next = pre->next;//next此时是pre的下一个节点 } } return guard->next; } };
看到别人的代码真的有重伤,自己脑子估计进水了这么简单的方法都没有想到,只要大于等于一个链表,小于一个链表,最后合并就好了。
class Solution { public: ListNode *partition(ListNode *head, int x) { if(head == NULL || head->next == NULL) return head; ListNode* left = new ListNode(-1); ListNode* right = new ListNode(-1); ListNode* l_h = left; ListNode* r_h = right; ListNode* cur = head; while(cur!=NULL) { if(cur->val < x) { l_h->next = cur; l_h = l_h->next; } else { r_h->next = cur; r_h = r_h->next; } cur = cur->next; } l_h->next = right->next; r_h->next = NULL; return left->next; } };
Copy List with Random Pointer
剑指offer上的有的,但是忘记了。
class Solution { public: void CloneNodes(RandomListNode* head) { RandomListNode* h = head; while(h != NULL) { RandomListNode* p1 = new RandomListNode(h->label); p1->next = h->next; h->next = p1; h = p1->next; } } void ConnectRandomLinks(RandomListNode *head) { RandomListNode* h = head; while(h!=NULL) { RandomListNode* p = h->next; if(h->random != NULL) p->random = h->random->next; h = p->next; } } RandomListNode *ReconnectNodes(RandomListNode *head) { RandomListNode* h = head; RandomListNode* clonedHead = NULL; RandomListNode* clonedNode = NULL; if(h != NULL) { clonedHead = clonedNode = h->next; h->next = clonedNode->next; h = h->next; } while(h!=NULL) { clonedNode->next = h->next; clonedNode = clonedNode->next; h->next = clonedNode->next; h = h->next; } return clonedHead; } RandomListNode *copyRandomList(RandomListNode *head) { if(head == NULL ) return head; CloneNodes(head); ConnectRandomLinks(head); return ReconnectNodes(head); } };
相关文章推荐
- Two pointers (1) -- Linked List Cycle II, Rotate List
- LeetCode解题报告—— Linked List Cycle II & Reverse Words in a String & Fraction to Recurring Decimal
- 【LeetCode】【C++】Linked list cycle 2
- 141. Linked List Cycle
- LeetCode OJ - Linked List Cycle
- 142. Linked List Cycle II
- [LeetCode] 92. Reverse Linked List II
- Leetcode: Linked List Cycle II
- [leetcode 141] Linked List Cycle
- [LeetCode 206] Reverse Linked List
- leetcode记录 Reverse Linked List
- leetcode -- Linked List Cycle II
- LeetCode Reverse Linked List II
- 92. Reverse Linked List II
- LeetCode: Linked List Cycle
- LeetCode 141: Linked List Cycle
- [leetcode]92. Reverse Linked List II
- 4.24 leetcode -24 linked-list-cycle
- CODE 138: Linked List Cycle
- 142. Linked List Cycle II