Insertion Sort List
pro:Sort a linked list using insertion sort.
sol:
新加一个root节点,指向head节点
定义两个指针,pre,cur用来遍历链表,一旦发现cur不比pre大,则需要将cur插入到前面
定义两个指针insertpre,insertcur,需要插入时将其分别初始化为root,head,找到insertcur大于cur的位置
将cur从后面删除(一步)、将cur插入前面(两步)、重置cur(一步)。对于链表操作每次要想清楚影响了几根线。还有关于双向链表的东西,更要思路清晰。
code:
class Solution {
public:
ListNode *insertionSortList(ListNode *head) {
if(head==NULL||head->next==NULL) return head;
ListNode *root = new ListNode(-1);
root->next = head;
ListNode *pre, *cur;
ListNode *insertpre, *insertcur;
pre = head, cur = head->next;
while (cur != NULL) {
if (cur->val >= pre->val) {
pre = cur, cur = cur->next;
continue;
} else {
insertpre = root;
insertcur = root->next;
while (insertcur->val < cur->val) {
insertpre = insertcur;
insertcur = insertcur->next;
}
pre->next = cur->next;
cur->next = insertcur;
insertpre->next = cur;
cur = pre->next;
}
}
return root->next;
}
}
Sort List
pro:对链表进行排序,要求O(nlog(n))时间复杂度,constant空间复杂度
sol:O(nlog(n))的时间复杂度想到用归并和快排,看了别人的思路说快排对这题交换次数太多了,只能用归并。
每次找到链表的中间节点mid,方法是fast slow指针的方法,将链表分成两份,注意别忘记将mid->next设置为NULL
归并时创建一个新节点root,值是当前两个表头的较小节点,然后root->next等于递归的处理,较小表头的链表表头移动。
code:
<span style="font-size:12px;">Class Solution
{
public:
ListNode* getMid(ListNode *head) {
ListNode* slow, *fast;
slow = fast = head;
while (fast->next != NULL && fast->next->next != NULL) {
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
ListNode* sortMerge(ListNode *node1, ListNode *node2) {
if (node1 == NULL) return node2;
if (node2 == NULL) return node1;
ListNode* root;
if (node1->val < node2->val) {
root = new ListNode(node1->val);
root->next = sortMerge(node1->next, node2);
} else {
root = new ListNode(node2->val);
root->next = sortMerge(node1, node2->next);
}
return root;
}
ListNode * sortList(ListNode * head) {
ListNode *mid, *next;
if (head == NULL || head->next == NULL) return head;
mid = getMid(head);
next = mid->next;
mid->next = NULL;
ListNode *one, *two;
one = sortList(head);
two = sortList(next);
head = sortMerge(one, two);
return head;
}
};</span>
Reorder List
pro:将一个链表按照一定顺序排列,如1 2 3 4 5,转化成1 5 2 4 3,即头和尾分别取一个
sol:先将链表reverse,记录链表的长度,然后就知道原链表和反链表进行merge的时候分别需要多少个了。
code:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
private:
int cnt;
public:
ListNode* reverse(ListNode *head)
{
ListNode* res=new ListNode(head->val);
ListNode* pre,*next;
ListNode* temp,*root;
pre=NULL;
root=head;
cnt=1;
while(1)
{
temp=root->next;
res->next=pre;
pre=res;
if(temp==NULL) break;
cnt++;
res=new ListNode(temp->val);
root=temp;
}
return res;
}
void reorderList(ListNode *head)
{
if(head==NULL||head->next==NULL) return;
cnt=0;
ListNode *root=reverse(head);
int i;
ListNode *res,*temp,*temp1,*temp2,*next1,*next2;
res=new ListNode(0);
temp=res;
temp1=head,temp2=root;
for(i=0;i<cnt/2;i++)
{
next1=temp1->next;
next2=temp2->next;
temp1->next=temp2;
temp->next=temp1;
temp=temp2;
temp1=next1;
temp2=next2;
}
if(cnt%2==0)
{
temp->next=NULL;
}else
{
next1->next=NULL;
temp->next=next1;
}
head=res->next;
}
};