-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Myfeature #1
Open
Apriluestc
wants to merge
5
commits into
yangwenmai:master
Choose a base branch
from
Apriluestc:myfeature
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Myfeature #1
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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% 的用户 | ||
* */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
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 | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ineffectual assignment to
headPre
(fromineffassign
)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个测试代码怎么弄啊
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
你还写 Go 代码?
他的意思是:对 headPre 的无效分配(来自 ineffassign lint)