归并排序类题目

归并排序类题目

介绍

说是归并排序类的题目其实就是合并过程这个部分的思想:两个序列(链表、数组或者字符串等),合并成为一个序列的问题

问题描述

在这里插入图片描述

问题分析

题目意思很明显了,两个链表合并。有一个需要注意的点:两个要合并链表的第一个节点判断数值大小之后用什么接着:虚拟头节点

代码表述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        //新的链表
        ListNode*node=new ListNode(-1);//建立虚拟头节点
        auto res=node;//要返回的节点
        //归并排序的思想了
        while(l1&&l2){
            if(l1->val<=l2->val){
                node->next=l1;
                l1=l1->next;//不要忘记了更新链表节点
            }
            else{
                node->next=l2;
                l2=l2->next;
            }
            node=node->next;
        }
        if(l1)node->next=l1;
        else if(l2)node->next=l2;
        return res->next;
    }
};

复杂度分析

时间复杂度:O(两个链表的长度)。需要遍历两个链表。
空间复杂度:O(1).两个节点的额外空间。

问题描述

在这里插入图片描述

问题分析

同理,合并排序的思路。但是这里A数组可以充当辅助数组的作用。

代码表述

class Solution {
public:
    void merge(vector<int>& A, int m, vector<int>& B, int n) {
        //双指针,从后面开始
        //A中的末尾有足够空间,所以可以先设定A的大小为A+B的大小,然后双指针比较AB两个集合中的元素大小,大的放在最末尾即可
        //注意可能有一方的元素提前取完,之后将剩下的直接放入数组即可
        int l=m;
        int r=n;
        while(l&&r){
            if(A[l-1]>=B[r-1]){//注意数组下标
                A[l+r-1]=A[l-1];
                l--;
            }
            else {
                A[l+r-1]=B[r-1];
                r--;
            }
        }
        if(l==0){
            while(r){
                A[r-1]=B[r-1];
                r--;
            }
        }
    }
};

复杂度分析

时间复杂度:O(两个数组的长度)。需要遍历两个链表。
空间复杂度:O(1)直接使用A的空间,没有使用额外空间。

问题描述

在这里插入图片描述

问题分析

思路也挺简单,对代码处理要熟悉。

代码表述

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 计算两个数之和
     * @param s string字符串 表示第一个整数
     * @param t string字符串 表示第二个整数
     * @return string字符串
     */
//     int re(int sum){
//         if(sum>=10)return 1;
//         else if(sum<10)return 0;
//     }
    string solve(string s, string t) {
        // write code here
        //二合一,感觉好多都是归并和插入排序的思路,排序牛逼
        int sum=0;//数字个位上的和
        int flag=0;//进位标志,进位表示1
        s='0'+s;//避免边界条件,如果最终第一个字符不是0,说明进位了
        t='0'+t;
        int i=s.size()-1;
        int j=t.size()-1;
        string str;
        while(i>=0&&j>=0){//循环截止条件都是细节
            sum=s[i]-'0'+t[j]-'0'+flag;
            //大于10就进一
            if(sum>=10){
                flag=1;
            }
            else if(sum<10){
                flag=0;
            }
            str+=to_string(sum%10);
            i--;
            j--;
        }
        //可能一个数字已经算完了
        while(i>=0){
            sum=s[i]-'0'+flag;
            if(sum>=10)flag=1;
            else if(sum<10)flag=0;
            str+=to_string(sum%10);
            i--;
        }
        while(j>=0){
            sum=t[j]-'0'+flag;
            if(sum>=10)flag=1;
            else if(sum<10)flag=0;
            str+=to_string(sum%10);
            j--;
        }
        //别忘了反转
        reverse(str.begin(), str.end());
        //如果第一个还是‘0’,那就两个首位就没有进1
        if(str[0]=='0')return str.substr(1);
        return str;
    }
};

复杂度分析

时间复杂度:O(两个字符序列的长度)。需要遍历两个字符序列。
空间复杂度:O(1)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值