zoukankan      html  css  js  c++  java
  • 线性时间将两个有序链表合成一个有序链表(constant additional space)

    description:

    given two sorted singly list, merge them into one using constant additional space

    algorithm:

    we will reference the two linked list as list1 and list2 for convenience,

    since list1 is sorted,just find the right position for each element in list2,

    detailed comments are added to the following code

    ps: the blog has been modified since some bugs have been tested

    the former version below is correct while the latter is wrong, I keep it just to remind myself to be independent and critical-thinking

    // Definition for singly-linked list.
    struct ListNode {
        int val;
        ListNode *next;
        ListNode(int x) : val(x), next(NULL) {}
    };
    
    class Solution {
    public:
        ListNode *sortList(ListNode *head) {
    		if(head == NULL)
    			return NULL;
    		ListNode* mid,*end;
    		int len;
    		getPara(head,&mid,&end,&len);
    		//cout << len << endl;  //only for debug
    		if(len == 1){
    			return head;
    		}
    		if(len == 2){
    			if(head->val > head->next->val){
    				int tmp = head->val;
    				head->val = head->next->val;
    				head->next->val = tmp;
    			}
    			return head;
    		}
    
    		end->next = NULL;
    		 ListNode* latterpart = sortList(mid->next,end,len >> 1);
    		mid->next = NULL;
    		//传入值之前修改这个可能更好
    		ListNode* formerpart = sortList(head,mid,(len+1)>>1);  //为什么formerpart会变为空指针
    
    		head = Merge(formerpart,latterpart);
    		return head;
    	}
    	void getPara(ListNode* head, ListNode**pmid,ListNode** pend,int*len){
    		(*len) = 0;
    		(*pmid) = head;
    		(*pend) = head;
    		if(head == NULL){
    			return;
    		}
    		//ListNode* (*pend) = head,*slowpointer = head;
    		(*len) = 1; //长度至少为1
    		while((*pend)->next != NULL && (*pend)->next->next != NULL){ //快指针每次向后跳两步,慢指针每次向后跳一步
    			(*pmid) = (*pmid)->next;
    			(*pend) = (*pend)->next->next;
    			(*len) += 2;
    		}
    		if((*pend)->next == NULL){  //长度为奇数
    			return;
    		}
    		if((*pend)->next->next == NULL){ //长度为偶数
    			(*len) += 1;
    			(*pend) = (*pend)->next;
    			return;
    		}
    	}
    	ListNode* sortList(ListNode* head,ListNode* end,int len){
    		if(len == 0){  //这里的条件太泛了所以貌似是写错了
    			return NULL;
    		}
    		if(len == 1){
    			head->next =NULL;  //注意修改
    			return head;
    		}
    		if(len == 2){
    			if(head->val > end->val){
    				int tmp = end->val;
    				end->val = head->val;
    				head->val = tmp;
    			}
    			end->next = NULL;
    			return head;
    		}
    		//int a[25] = {1,3,6,7,8,9,56,67,211,763,2,4,5,10,11,12,13,300,500,800};
    		ListNode* newmid,*newend;
    		int halflen;
    		getPara(head,&newmid,&newend,&halflen);  //此处其实还可以优化,但出于代码复用的考虑
    
    		newend->next = NULL;
    		ListNode* latterpart = sortList(newmid->next,newend,halflen >> 1);
    		newmid->next = NULL;
    		ListNode* formerpart = sortList(head,newmid,(halflen+1)>>1);
    
    		head = Merge(formerpart,latterpart);
    		return head;
    	}
    	ListNode* Merge(ListNode* part1, ListNode*part2){  //Merge这里写的有问题诶
    		if(part1 == NULL)
    			return part2;
    		if(part2 == NULL)
    			return part1;
    		//part1 != NULL && part2 != NULL
    		ListNode* tmpp1 = part1, *tmpp2 = part2;
    		bool first = true; //finally figured out the reason to use first,to indicate whether it's the first comparison
    		ListNode* head = NULL;
    		ListNode* last = NULL;
    		ListNode* tmpformer = NULL;
    		while(tmpp1 != NULL && tmpp2 != NULL){
    			bool enterloop = false;;
    			while(tmpp1 != NULL && tmpp2->val >= tmpp1->val){
    			//if and only if the condition in while loop is satisfied the control flow can reach here
    				tmpformer = tmpp1;
    				if(first){
    					first = false;
    					head = tmpformer;
    				}
    				enterloop = true;
    				tmpp1 = tmpp1->next;
    			}
    			if(tmpp1 == NULL){  //even if the big while is first carried out, control flow might reach here
    				tmpformer->next = tmpp2;
    				if(first){
    					first = false;
    					head = part1;
    				}
    				return head;
    			}
    			ListNode* tmpnextoftmpp2 = tmpp2->next;
    			tmpp2->next = tmpp1;
    			if(enterloop){
    				tmpformer->next = tmpp2;
    				//last = tmpp2;
    				if(first){
    					first = false;
    					head = part1;
    				}
    			}
    			else{
    				if(last != NULL){
    					last->next = tmpp2;
    				}
    				if(first){
    					first = false;
    					head = tmpp2;
    				}
    			}
    			last = tmpp2;
    			tmpp2 = tmpnextoftmpp2;
    
    			//last = tmpformer;
    		}
    		return head;
    	}
    };
    

      

    #include<iostream>
    #include<cstdio>
    #include<string.h>
    #include<string>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    class Node{
    public:
    	int value;
    	Node* Next;
    	Node(int v_ = 0, Node* Next_ = NULL):value(v_),Next(Next_){}
    };
    /*Node* Merge2(Node* head1, Node* head2)
    {
    	Node* res,*ret;
    	if(head1 == NULL) return head2;
    	if(head2 == NULL) return head1;
    	Node* p = head1;
    	Node* q = head2;
    	
    	if(p->value < q->value)
    	{
    		res = p;
    		p = p->Next;
    	}
    	else
    	{
    		res = q;
    		q = q->Next;
    	}
    	ret = res;
    	while(p && q)
    	{
    		if(p->value < q->value)
    		{
    			res->Next = p;
    			res = p;
    			p = p->Next;
    		}
    		else
    		{
    			res->Next = q;
    			res = q;
    			q = q->Next;
    		}
    	}
    	while(p)
    	{
    	         res->Next = p;
                      res = p;
    		p = p->Next;
    	}
    	while(q)
    	{
    		res->Next = q;
    		res = q;
    		q = q->Next;
    	}
    	return ret;
    }*/
    Node* Merge2(Node*p1,Node*p2){
    	if(p1 == NULL)
    		return p2;
    	if(p2 == NULL)
    		return p1;
    	Node *tmpp1 = p1,*tmpp2 = p2;
    	Node*head;
    	bool first = true;
    	/*core optimization: if tmpp2 find its place in list1, then tmpp2->next must be after its position,so both list1 and list2
    	  are enumerated only once, which implements linear algorithm*/
    	while(tmpp1 != NULL && tmpp2 != NULL){
    		Node* tmpformer = NULL;
    		while(tmpp1 != NULL && tmpp2->value > tmpp1->value){ 
    			tmpformer = tmpp1;
    			tmpp1 = tmpp1->Next;
    		}
    		if(tmpp1 == NULL){
    			tmpformer->Next = tmpp2;
    			if(first){
    				first = false;
    				head = p1;
    			}
    			break;
    		}
    		//tmpp2的value值比tmpp1的value值小但是比tmpformer的value值大
    		Node* tmprecordp2 = tmpp2->Next;
    		tmpp2->Next = tmpp1;
    		if(tmpformer != NULL){
    			tmpformer->Next = tmpp2;
    			if(first){
    				first = false;
    				head = p1;
    			}
    		}
    		else{
    			if(first){
    				first = false;
    				head = p2;
    			}
    		}
    		tmpp2 = tmprecordp2;
    	}
    	return head;
    }
    int main(){
    	Node* p1[10], *p2[10];
    	memset(p1,0,sizeof(p1));
    	memset(p2,0,sizeof(p2));
    	int a[25] = {1,3,6,7,8,9,56,67,211,763,2,4,5,10,11,12,13,300,500,800};
    	/*initalization*/
    	for(int i = 0; i < 10; ++i){
    		p1[i] = new Node(a[i]);
    	}
    	for(int i = 0; i < 10; ++i){
    		p2[i] = new Node(a[10+i]);
    	}
    	Node* pp1,*pp2;
    
    	for(int i = 0; i < 9; ++i){
    	//	cout << &(p1[i]->Next) << endl;
    		p1[i]->Next = p1[i+1];
    	}
    	for(int i = 0; i < 9; ++i){
    		p2[i]->Next = p2[i+1];
    	}
    		pp1 = p1[0];
    	while(pp1 != NULL){
    		cout << pp1->value << '	';
    		pp1 = pp1->Next;
    	}
    	cout << endl;
    	pp2 = p2[0];
    	while(pp2 != NULL){
    		cout << pp2->value << '	';
    		pp2 = pp2->Next;
    	}
    	cout << endl;
    	/*initialization end*/
    	Node* res = Merge2(p1[0],p2[0]);
    	while(res!=NULL){
    		cout << res->value << endl;
    		res = res->Next;
    	}
    	for(int i = 0; i < 10; ++i){
    		delete p1[i];
    	}
    	for(int i = 0; i < 10; ++i){
    		delete p2[i];
    	}
    	return 0;
    }
    

    key points:

    1.pay special attention to keep head pointer, which is easily lost,

      my solution is to set a flag bool variance, which is linear complexity but somewhat inefficient

      perhaps it has potential to improve

    2.avoid misorder of pointer

    3.special condition: if (p1 == NULL) return p2;

                                if(p2 == NULL ) return p1;

    4.when search for the postion for a certain element in list1, note that it might be above any element in list1 so tmpp1 might reach its end(value equals NULL) during search

  • 相关阅读:
    C++:Ubuntu 中GCC和G++的安装
    pycharm所有包
    机器学习--推荐引擎
    均值漂移法 + 轮廓系数+DBSCAN算法
    聚类模型
    事件预测 -- 解决分类问题
    网格搜索
    置信概率
    样本类别均衡化
    爬虫用到的知识点
  • 原文地址:https://www.cnblogs.com/warmfrog/p/3695250.html
Copyright © 2011-2022 走看看