LeetCode周练Contest-36代码解析(C++)

写在前面:

LeetCode这个网站相比不必多说了吧,凡是IT圈子的人应该都知道这个网站,最近开始准备找工作,当然也免不了上去刷刷题,做一做比较经典的编程题,刚好看到LeetCode有个周练,便报名参加。

进入正题:

概要: 总共4个题,一个半小时的时间安排。题目分级为,两个easy,一个medium,一个hard。

第一题 617. Merge Two Binary Trees

题目描述

Given two binary trees and imagine that when you put one of them to cover the other, some nodes of the two trees are overlapped while the others are not.

You need to merge them into a new binary tree. The merge rule is that if two nodes overlap, then sum node values up as the new value of the merged node. Otherwise, the NOT null node will be used as the node of new tree.


其实就是一道开胃菜的题目而已,树形结构,二叉树的题目,就是合并两棵二叉树,合并规则为相加,使用递归的方法来做。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        if(t1 == NULL && t2 == NULL)    return NULL;
        TreeNode* new_node = new TreeNode(0);
        new_node->val = (t1==NULL?0:t1->val) + (t2==NULL?0:t2->val);
        new_node->left = mergeTrees(t1==NULL?NULL:t1->left, t2==NULL?NULL:t2->left);
        new_node->right = mergeTrees(t1==NULL?NULL:t1->right, t2==NULL?NULL:t2->right);
        return new_node;
    }
};

第二题 604. Design Compressed String Iterator

题目描述

None


这道题目后面再去看,需要prime才能打开看了,不过根据代码回忆,这道题的要求是设计一个类,然后这个类负责将压缩后的字符串解压缩,并且一定需要提供两个成员函数,一个成员函数为next,负责输出下一个迭代器的值;第二个成员函数为hasNext,负责输出一个bool值,判断是否还有下一个值可以输出;

根据题意,可以设计一个构造函数,输入为压缩字符串,在构造函数中,可以对压缩字符串进行解压缩,需要注意的是,有可能会出现a1234567890这种数,如果单纯的给a构造那么多个重复的字符出来会造成MLE,所以可以考虑用一个二维数组来保存模拟解压缩之后的状态,每一维数组有两位,第一位表示字符,第二位表示有多少个字符,之后就可以完成顺序去返回迭代器和是否能够弹出有效字符的成员函数;

//MLE
class StringIterator {
private:
    string _ori;
    vector<vector<long long>> _table;

    void processString(string &s){
        string ret;
        int lens = s.size();
        for(int i=0;i<lens;){
            if(!(s[i]>='0'&&s[i]<='9')){
                int start = ++i;
                while(i<lens){
                    if(s[i]>='0'&&s[i]<='9')    ++i;
                    else    break;
                }
                int end = i;
                long long nums = stoi(s.substr(start, end-start));
                long long index = start - 1;
                _table.push_back({index, nums});
            }
        }
    }
public:
    StringIterator(string compressedString) {
        _ori = compressedString;
        processString(_ori);
    }
    
    char next() {
        for(int i=0;i<_table.size();i++){
            if(_table[i][1]>0){
                _table[i][1]--;
                return _ori[_table[i][0]];
            }
        }
        return ' ';
    }
    
    bool hasNext() {
        for(int i=0;i<_table.size();i++){
            if(_table[i][1]>0){
                return true;
            }
        }
        return false;
    }
};

/**
 * Your StringIterator object will be instantiated and called as such:
 * StringIterator obj = new StringIterator(compressedString);
 * char param_1 = obj.next();
 * bool param_2 = obj.hasNext();
 */

第三题 611. Valid Triangle Number

题目描述

Given an array consists of non-negative integers, your task is to count the number of triplets chosen from the array that can make triangles if we take them as side lengths of a triangle.


先解释下题目,就是有一串数字,从中选择三个数可以组成一个三角形,问总共有多少种组合方法;

LeetCode上有一类题,可以归纳为k-sum,比较经典,这个题可以借助3-sum的思路来做,唯一不同的是,这里选择的三个数需要组成一个三角形,满足的是三角形的三条边的定律:a+b > c;所以可以先将一维数组排序之后,使用夹逼的方法来做,这里需要注意的是,在夹逼的时候,不能固定最前端的数,需要固定最后端的数;因为固定最后端的数以后,分别选择未被固定的数组中,第一位为a,最后一位为b,如果a+b大于c,那么可以肯定的是从a到b之间的任何数都可以和b组合然后连上c组成三角形的三条边,如果不行,那就需要b往左移动一步,然后再判断;

如果固定的是数组第一位,那么未被固定的数组中,当不满足(最后一位 - 第一位 < 固定值),之后的第一位和最后一位,无论是第一位向右,还是最后一位向左,都是使得条件朝着满足的方向进行,这样做不能带来比较妥善的处理方式,要想不漏掉任何一个可能的组合,会使得时间复杂度提升为平方,甚至于三次方;

代码如下:

//TLE
class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        int lens = nums.size();
        if(lens < 3)    return 0;
        sort(nums.begin(), nums.end());
        int ret = 0;
        for(int i=0;i<lens-2;i++){
            for(int j=i+1;j<lens-1;j++){
                for(int k=j+1;k<lens;k++){
                    ret += nums[i]+nums[j]>nums[k]?1:0;
                }
            }
        }
        return ret;
    }
};

//类似于k-sum那道题,夹逼来做
class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        int lens = nums.size();
        if(lens < 3)    return 0;
        sort(nums.begin(), nums.end());
        int ret = 0;
        //必须固定后面的,然后在前面夹逼
        for(int i=lens-1;i>=2;i--){
            int left = 0, right = i - 1;
            while(left < right){
                if(nums[right] + nums[left] > nums[i]){
                    ret += right - left;
                    --right;
                }
                else    ++left;
            }
        }
        return ret;
    }
};

第四题 616. Add Bold Tag in String

题目描述

None.


很抱歉,这道题后面再去看的时候也加入了prime套餐;根据代码来回忆吧;

题意为给定一个字符串,一个字符串数组,数组中的每一个字符串为原始字符串的子串,如果在原始字符串中有出现,那就需要在选中的字符串子串两端加上HTML中的加粗标签,即:<b></b>;如果有重复,那就保持重叠之后再加上标签;

这道题其实虽然是medium的难度,但是很简单,可以维护一个和原来字符串同样大小的bool型数组,然后遍历每一个字符串子串,如果在原始字符串中有出现过,就将bool型数组中相应位置置为true;最后根据bool型数组输出添加标签的字符串;该方法时间复杂度比较高,不过不失为一种快速完成程序的方法;

class Solution {
public:
    string addBoldTag(string s, vector<string>& dict) {
        int s_lens = s.size();
        vector<bool> marks(s_lens, false);
        int lens = dict.size();
        for(int i=0;i<lens;i++){
            int start = 0, pos = 0;
            while((pos = s.find(dict[i], start))!=string::npos){
                for(int j=pos;j<pos+dict[i].size();j++){
                    marks[j] = true;
                }
                start = pos + 1;
            }
        }
        string ret;
        //查找一个字符串的情况
        for(int i=0;i<s_lens;){
            if(marks[i]){
                ret += "<b>";
                while(i<s_lens){
                    if(marks[i])    ret.push_back(s[i++]);
                    else    break;
                }
                ret += "</b>";
            }
            else{
                ret.push_back(s[i++]);
            }
        }
        return ret;
    }
};

总结:

找工作路漫漫,但求不忘初心,回首对得起走过的路。

代码地址:[luuuyi/leetcode-contest]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值