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

  • 相关阅读:
    JSON的基本认识
    Linux基础 7-10 Bash编程练习4--for循环
    Linux基础7-9 Bash编程--for循环语句
    linux基础 7-3-条件判断语句案例
    Linux基础 7-8 sed命令使用练习
    Linux基础 7-7 set命令的使用
    Linux基础 7-6 Bash脚本编程练习3
    Linux基础7-5 Bash脚本编程--算术运算
    Linux基础7-4 Bash脚本编程练习2
    Linux基础 7-3 Bash脚本编程--条件判断
  • 原文地址:https://www.cnblogs.com/warmfrog/p/3695250.html
Copyright © 2011-2022 走看看