From 37b59d9d656a4f53078accbb2069e858514dd5b7 Mon Sep 17 00:00:00 2001 From: Shiny-Man <239194147@qq.com> Date: Thu, 16 May 2019 23:27:08 +0800 Subject: [PATCH 1/5] 1 --- tets.go | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tets.go diff --git a/tets.go b/tets.go new file mode 100644 index 0000000..7f88b1e --- /dev/null +++ b/tets.go @@ -0,0 +1,8 @@ +package main + +import "fmt" + +func main(){ + fmt.Println("Hello, World!") +} + From e94385d1b0c012d95adbd778da4f7a9669658855 Mon Sep 17 00:00:00 2001 From: Shiny-Man <239194147@qq.com> Date: Thu, 16 May 2019 23:30:50 +0800 Subject: [PATCH 2/5] 1 --- tets.go | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 tets.go diff --git a/tets.go b/tets.go deleted file mode 100644 index 7f88b1e..0000000 --- a/tets.go +++ /dev/null @@ -1,8 +0,0 @@ -package main - -import "fmt" - -func main(){ - fmt.Println("Hello, World!") -} - From 18aca38872b39e7a680dbabdffa9a40ab68a8a8c Mon Sep 17 00:00:00 2001 From: Shiny-Man <239194147@qq.com> Date: Thu, 16 May 2019 23:47:42 +0800 Subject: [PATCH 3/5] feat(practive): start LeetCode 148 --- practive/leetcode/0148.sort-list/148.h | 69 ++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 practive/leetcode/0148.sort-list/148.h diff --git a/practive/leetcode/0148.sort-list/148.h b/practive/leetcode/0148.sort-list/148.h new file mode 100644 index 0000000..ab52ef7 --- /dev/null +++ b/practive/leetcode/0148.sort-list/148.h @@ -0,0 +1,69 @@ +/* + * 在 O(nlogn) 时间复杂度和常数级空间复杂度下,对链表进行排序。 + * */ + +struct ListNode { + int val; + ListNode* next; + ListNode(int x) + :val(x) + ,next(nullptr) + {} +}; + +/* + * 参考:Sort List——经典(链表中的归并排序) https://www.cnblogs.com/qiaozhoulin/p/4585401.html + * 归并排序法:在动手之前一直觉得空间复杂度为常量不太可能,因为原来使用归并时,都是 O(N)的, + * 需要复制出相等的空间来进行赋值归并。对于链表,实际上是可以实现常数空间占用的(链表的归并 + * 排序不需要额外的空间)。利用归并的思想,递归地将当前链表分为两段,然后merge,分两段的方 + * 法是使用 fast-slow 法,用两个指针,一个每次走两步,一个走一步,知道快的走到了末尾,然后 + * 慢的所在位置就是中间位置,这样就分成了两段。merge时,把两段头部节点值比较,用一个 p 指向 + * 较小的,且记录第一个节点,然后 两段的头一步一步向后走,p也一直向后走,总是指向较小节点, + * 直至其中一个头为NULL,处理剩下的元素。最后返回记录的头即可。 + * 主要考察3个知识点, + * 知识点1:归并排序的整体思想 + * 知识点2:找到一个链表的中间节点的方法 + * 知识点3:合并两个已排好序的链表为一个新的有序链表 + * */ + +class Solution { +public: + ListNode* sortList(ListNode* head) { + if (head == nullptr || head->next == nullptr) { + return head; + } + ListNode* left = head, *middle = left, *right = head; + while(right && right->next) { + right = right->next->next; + middle = left; + //跳出循环前,left 为中间节点,跳出后往后移动一位,指向 middle 后面的链表 + left = left->next; + } + //将链表分成两部分,前一部分以 middle 结尾,应该置空,后一阶段以 left 开头 + middle->next = nullptr; + //分别对 head、left 链表进行排序(合并两个有序链表) + return merge(sortList(head), sortList(left)); + } +private: + //merge list + ListNode* merge(ListNode* l1, ListNode* l2) { + if(l1 == nullptr) { + return l2; + } + if(l2 == nullptr) { + return l1; + } + if(l1->val <= l2->val) { + l1->next = merge(l1->next, l2); + return l1; + } else { + l2->next = merge(l1, l2->next); + return l2; + } + } +}; + +/* + * 执行用时 : 68 ms, 在Sort List的C++提交中击败了96.75% 的用户 + * 内存消耗 : 12.7 MB, 在Sort List的C++提交中击败了55.93% 的用户 + * */ From 67561351c63aee092b40fc289eacad3ae51118a9 Mon Sep 17 00:00:00 2001 From: Shiny-Man <239194147@qq.com> Date: Fri, 17 May 2019 08:58:07 +0800 Subject: [PATCH 4/5] 20190517-sort-list --- practive/leetcode/0148.sort-list/sort-list.go | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100755 practive/leetcode/0148.sort-list/sort-list.go diff --git a/practive/leetcode/0148.sort-list/sort-list.go b/practive/leetcode/0148.sort-list/sort-list.go new file mode 100755 index 0000000..9ef281d --- /dev/null +++ b/practive/leetcode/0148.sort-list/sort-list.go @@ -0,0 +1,68 @@ +package problem0148 + +/* +Sort a linked list in O(n log n) time using constant space complexity. + +Example 1: + +Input: 4->2->1->3 +Output: 1->2->3->4 +Example 2: + +Input: -1->5->3->4->0 +Output: -1->0->3->4->5 +*/ + +// ListNode 是题目预定义的数据类型 +type ListNode = kit.ListNode + +func sortList(head *ListNode) *ListNode { + if head == nil || head.Next == nil { + return head + } + left, right := split(head) + return merge(sortList(left), sortList(right)) +} +// 从中间位置,切分 list +func split(head *ListNode) (left, right *ListNode) { + // head.Next != nil + // 因为, sortList 已经帮忙检查过了 + // fast 的变化速度是 slow 的两倍 + // 当 fast 到达末尾的时候,slow 正好在 list 的中间 + slow, fast := head, head + var slowPre *ListNode + for fast != nil && fast.Next != nil { + slowPre, slow = slow, slow.Next + fast = fast.Next.Next + } + // 斩断 list + slowPre.Next = nil + // 使用 slowPre 是为了确保当 list 的长度为 2 时,会均分为两个长度为 1 的子 list + left, right = head, slow + return +} +// 把已经排序好了的两个 list left 和 right +// 进行合并 +func merge(left, right *ListNode) *ListNode { + // left != nil , right != nil + + // 因为, sortList 已经帮忙检查过了 + + cur := &ListNode{} + headPre := cur + for left != nil && right != nil { + // cur 总是接上较小的 node + if left.Val < right.Val { + cur.Next, left = left, left.Next + } else { + cur.Next, right = right, right.Next + } + cur = cur.Next + } + // 处理 left 或 right 中,剩下的节点 + if left == nil { + cur.Next = right + } else { + cur.Next = left + } +} From 6e998d34581cb7f0b9dc580339b0d4355fb080ce Mon Sep 17 00:00:00 2001 From: Shiny-Man <239194147@qq.com> Date: Fri, 17 May 2019 09:01:52 +0800 Subject: [PATCH 5/5] 20190517-sort-list --- practive/leetcode/0148.sort-list/sort-list.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/practive/leetcode/0148.sort-list/sort-list.go b/practive/leetcode/0148.sort-list/sort-list.go index 9ef281d..5e07673 100755 --- a/practive/leetcode/0148.sort-list/sort-list.go +++ b/practive/leetcode/0148.sort-list/sort-list.go @@ -1,6 +1,7 @@ package problem0148 /* +----------------------------- Sort a linked list in O(n log n) time using constant space complexity. Example 1: @@ -11,6 +12,7 @@ Example 2: Input: -1->5->3->4->0 Output: -1->0->3->4->5 +-------------------------- */ // ListNode 是题目预定义的数据类型