leetcode Merge Two Sorted Lists 回顾归并排序

这题属于easy型的题目,考的东西也很简单,就一个考点归并排序。但是算法这种东西就是太久没有接触,总是容易忘记,虽然算法的思想知道,但是要自己写的时候也总是遇到各种各样的细节性的问题,现在就由这个问题出发,再次复习一下归并排序的算法。

先看题目

你两个链表的头指针,链表的东西已经排好序了。最后要返回一个完全排好序的链表头。

算法思路:很简单:给的两个指针,分别指向两个排好序的数组(这一点很重要)。怎么进行归并排序呢?每次比较这两个头指针的内容大小,小的就加到新的链表里面,再移动这个指针,当某个指针指到尾的时候,再看另外一个指针,如果另外一个指针没有指到尾部,那么直接把这个指针后面的内容添加到新的链表后面,这样执行后,就可以得到一个把两个有序数组归并成排好序的链表。

伪代码

output: ans   //指向最后有序的数列指针

while(l1!=NULL&&l2!=NULL)

{
if(l1->val<l2->val)

//移动l1指针,并且添加到ans后面

else

//移动l2指针,并且添加到ans后面

}

while(l1!=NULL)

{

//移动l1的指针,并且添加到ans后面

}

while(l2!=NULL)

{

//移动l2的指针,并且添加到ans后面

}

              //最终的得到ans一个有序的数列指针



  细节问题:1、由于ans要不断的移动,但是最后是要返回ans的一个头指针,这里就需要对ans进行一个保护

      2、一定要小心l1,l2是空指针的情况,虽然在这里也不要特别注意,但是在做关于有指针的时候一定要小心指针为空的情况!!!

     3、由于不断要new新的单元,要小心添加到多余的元素。

        答案代码:(感觉很不规范,可以更简略更优美)

ListNode* mergeTwoLists(ListNode* l1, ListNode* l2)
    {
        if(l1==NULL&&l2==NULL)
        return NULL;
   
       if(l1==NULL&&l2!=NULL)
       
return l2;
        if(l2==NULL&&l1!=NULL)
        return l1;
        ListNode* ans=new ListNode(0);
        ListNode* te=ans;
        while(l1!=NULL&&l2!=NULL)
        {
            if(l1->val<=l2->val)
            {
                ans->val=l1->val;
       
             l1=l1->next;
               
    if(l1==NULL)
               
      break;
               
    ans->next=new ListNode(0);
               
 ans=ans->next;
                
           
   }
            else
            {
                ans->val=l2->val;
                l2=l2->next;
                if(l2==NULL)
                break;
                ans->next=new ListNode(0);
                ans=ans->next;
                
            }
        }
        while(l1!=NULL)
        {
            
            ans->next=new ListNode(0);
            ans=ans->next;
            ans->val=l1->val;
            l1=l1->next;
        }
      while(l2!=NULL)
        {
            
         
   ans->next=new ListNode(0);
            ans=ans->next;
            ans->val=l2->val;
            l2=l2->next;
       
   }
        return te;
    }



           问题扩展:到现在为止,这个题目就已经解决了,但是做这一题的真正目的是为了复习归并排序。一个数组,怎么对它进行归并排序呢,这个题目是对两个已经排好序的数组可以这样进行组合,那对于一整个数组,我们可以不断的进行划分,一开始长度为n,可以划分为两个长度为n/2的数组,那怎样对这两个进行划分排序呢!这两个可能不是有序,那就继续划分,当划分的两个数组都只有一个元素的时候,那它就肯定是有序的啦!然后就可以不断的归并,最后就可以得到整一个有序的数组。整个过程就可以像一棵树一样,不断的往下扩,一部分变成两部分,这可以就是一个递归的过程吗!

归并排序代码

void merge(int a[],int left,int right)//left,right分别为要排序的左右两边边界
{
if(left<right)
{
int mid=(left+right)/2;
merge(a,left,mid);   //不断的递归,划分
merge(a,mid+1,right);
int i=left;//i,j 分别为指向两个有序组的指针
int j=mid+1;
int* temp=new int[right-left]; //临时保存归并的数组单元
int k=0;
while(i<=mid&&j<=right)
{
if(a[i]<a[j])
{
temp[k++]=a[i++];
}
else
temp[k++]=a[j++];
}
while(i<=mid)
temp[k++]=a[i++];
while(j<=right)
temp[k++]=a[j++];
k=left;
i=0;
while(k<=right)
{
a[k]=temp[i];
k++;
i++;
}
delete []temp;
}


总结这一到题目虽然很简单,但是通过这一道题目,自己也回顾了一下归并排序算法,感觉还是学到了一点东西。代码这一块不写还真是容易忘记,虽然思想还是记得到,但是其实其后面有很多细节的东西,需要注意的,而这些问题,只有自己亲自写了代码才知道!

再拓展:网上还有一种非递归过程的归并排序算法,但是一直没怎么看懂,也没亲自试过!下次再看看非递归的归并排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值