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

  • 相关阅读:
    pip安装软件时出现Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build*的解决方案
    tidb安装
    TIDB 5.0 安装体验 怎么快速玩起来
    利用Tampermonkey(油猴)+ IDM 实现百度云盘大文件下载(IDM安装教程)
    python字典及相关操作
    【转载】CEO:我需要什么样的产品经理?
    2014年3月第三周/第一次跳槽、心情低潮期、与老总沟通问题
    hello word!
    function(event)中的event详解
    CSS 伪类
  • 原文地址:https://www.cnblogs.com/warmfrog/p/3695250.html
Copyright © 2011-2022 走看看