【Leetcode】第14场双周赛

第14场双周赛

难度不大,本菜平时勉强三题水平,这次一小时a了。没有特别难的题,基本上一题题慢慢做就可以了。最后一题这次想到了也不难。因为以往只有会员才能看双周赛题,所以记录一下。贴的代码都是比赛时写的,很朴素的方法,肯定有更好的解法,欢迎指正。

No.5112 十六进制魔术数字

你有⼀个⼗进制数字,请按照此规则将它变成「⼗六进制魔术数字」:⾸先将它变成字⺟⼤写的⼗六进制字符
串,然后将所有的数字 0 变成字⺟ O ,将数字 1 变成字⺟ I 。
如果⼀个数字在转换后只包含 {“A”, “B”, “C”, “D”, “E”, “F”, “I”, “O”} ,那么我们就认为这个转换是
有效的。
给你⼀个字符串 num ,它表示⼀个⼗进制数 N ,如果它的⼗六进制魔术数字转换是有效的,请返回转换后的结
果,否则返回 “ERROR” 。
示例 1:
输⼊:num = “257”
输出:“IOI”
解释:257 的⼗六进制表示是 101 。
示例 2:
输⼊:num = “3”
输出:“ERROR”

提示:
1 <= N <= 10^12
给定字符串不会有前导 L 。
结果中的所有字⺟都应该是⼤写字⺟。

要注意一下N的范围是10^12,也就是说不一定能用int表示,所以用了long先把num表示成数,然后转成16进制,再判断一下是否符合要求就行了。


class Solution {
public:
    char c[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    string toHexspeak(string num) {
        string res="";
        long number=0;
        for(char cc:num) number=number*10+cc-'0';
        while(number){
            res.push_back(c[number%16]);
            number/=16;
        }
        reverse(res.begin(),res.end());
        int n=res.size();
        for(int i=0;i<n;i++){
            if(res[i]=='0') res[i]='O';
            if(res[i]=='1') res[i]='I';
            else if(res[i]>='A') continue;
            else return "ERROR";
        }
        return res;
    }
};

No.5113 删除区间

给你⼀个 有序的 不相交区间列表 intervals 和⼀个要删除的区间 toBeRemoved , intervals 中的每⼀个区间 intervals[i] = [a, b] 都表示满⾜ a <= x < b 的所有实数 x 的集合。
我们将 intervals 中任意区间与 toBeRemoved 有交集的部分都删除。
返回删除所有交集区间后, intervals 剩余部分的 有序 列表。

示例 1:
输⼊:intervals = [[0,2],[3,4],[5,7]], toBeRemoved = [1,6]
输出:[[0,1],[6,7]]
示例 2:
输⼊:intervals = [[0,5]], toBeRemoved = [2,3]
输出:[[0,2],[3,5]]
提示:
1 <= intervals.length <= 10^4
-10^9 <= intervals[i][0] < intervals[i][1] <= 10^9

这边区间都是10^9范围的所以不能开数组去标记每个点是否有被删除。已经是有序的了,所以依次处理一下。


class Solution {
public:
    vector<vector<int>> removeInterval(vector<vector<int>>& intervals, vector<int>& toBeRemoved) {
        vector<vector<int>> res;
        int n=intervals.size();
        for(int i=0;i<n;i++){
            if(intervals[i][1]<=toBeRemoved[0]||intervals[i][0]>=toBeRemoved[1]){
                res.push_back(intervals[i]);
            }//和删除区间无交点,直接放进去
            else{
                if(intervals[i][1]<=toBeRemoved[1]){
                    if(intervals[i][0]<toBeRemoved[0]){
                        res.push_back({intervals[i][0],toBeRemoved[0]});
                    }//对应[1,3]删除[2,4]情形,剩下[1,2]
                }
                else{
                    if(intervals[i][0]<toBeRemoved[0]){
                        res.push_back({intervals[i][0],toBeRemoved[0]});
                        res.push_back({toBeRemoved[1],intervals[i][1]});//被删除部分被包含于intervals[i]
                    }
                    else{
                        res.push_back({toBeRemoved[1],intervals[i][1]});//对应于[2,4]删除[1,3]情形,剩下[3,4]
                    }
                }
            }
        }
        return res;
    }
};

No.5114 删除树节点

给你⼀棵以节点 L 为根节点的树,定义如下:

节点的总数为 nodes 个;

第 i 个节点的值为 value[i] ;

第 i 个节点的⽗节点是 parent[i] 。

请你删除节点值之和为 L 的每⼀棵⼦树。

在完成所有删除之后,返回树中剩余节点的数⽬。

示例:
【Leetcode】第14场双周赛_第1张图片

输⼊:nodes = 7, parent = [-1,0,0,1,2,2,2], value = [1,-2,4,0,-2,-1,-1]

输出:2

提示:

1 <= nodes <= 10^4

-10^5 <= value[i] <= 10^5

parent.length == nodes

parent[0] == -1 表示节点 0 是树的根。

这题大概就是考个指针的运用,开个结构体存一下节点的信息。直接贴的比赛时候的代码,写的比较乱…但是大体结构还是清晰的

class Solution {
public:
    struct node{
        int id;
        int val;
        vector<node*> childs;
        node(int a,int v){
            id=a;val=v;
        }
    };
    unordered_map<int,node*> m;//id和指针的映射
    unordered_map<node*,pair<int,int>> hash;//指针和对应的{子树和,子树节点个数}映射
    int cnt;
    //dfs一遍树,得到hash相关信息
    void dfs(node* root){
        if(!root) return ;
        int res=root->val;
        int number=1;
        for(node* child:root->childs){
            dfs(child);
            res+=hash[child].first;
            number+=hash[child].second;
        }
        hash[root]={res,number};
    }
    //遇到子树和为0的,直接删了,否则继续dfs
    void f(node* root){
        if(!root) return ;
        for(node* child:root->childs){
            if(hash[child].first==0){
                cnt-=hash[child].second;
            }
            else f(child);
        }
    }
    int deleteTreeNodes(int nodes, vector<int>& parent, vector<int>& value) {
        int n=parent.size();
        for(int i=0;i<n;i++){
            node* tmp=new node(i,value[i]);
            m[i]=tmp;
        }
        //这里怕测试数据中,parent数组中有节点的父亲出现在该节点之后,所以这边分了两部分建树
        for(int i=0;i<n;i++){
            if(parent[i]!=-1) m[parent[i]]->childs.push_back(m[i]);           
        }
        dfs(m[0]);
        cnt=nodes;
        f(m[0]);
        return cnt;
    }
};

No.5115 矩形内船只的数目

在用笛卡尔坐标系表示的二维海平面上,有一些船。每一艘船都在一个整数点上,且每一个整数点最多只有 1 艘船。

有一个函数 Sea.hasShips(topRight, bottomLeft) ,输入参数为右上角和左下角两个点的坐标,当且仅当这两个点所表示的矩形区域(包含边界)内至少有一艘船时,这个函数才返回 true ,否则返回 false 。

给你矩形的右上角 topRight 和左下角 bottomLeft 的坐标,请你返回此矩形内船只的数目。题目保证矩形内 至多只有 10 艘船。

调用函数 hasShips 超过400次 的提交将被判为 错误答案(Wrong Answer) 。同时,任何尝试绕过评测系统的行为都将被取消比赛资格。

示例:
【Leetcode】第14场双周赛_第2张图片
输入:
ships = [[1,1],[2,2],[3,3],[5,5]], topRight = [4,4], bottomLeft = [0,0]
输出:3
解释:在 [0,0] 到 [4,4] 的范围内总共有 3 艘船。

提示:

ships 数组只用于评测系统内部初始化。你无法得知 ships 的信息,所以只能通过调用 hasShips 接口来求解。
0 <= bottomLeft[0] <= topRight[0] <= 1000
0 <= bottomLeft[1] <= topRight[1] <= 1000

题的意思大概就是,现在有一些船,给一个矩形范围,让你计算这个范围内有多少船。但是我们只能通过一个API:判断某个范围内是否有船 来给出答案。这个题在之前看别人面经的时候看到过有类似的问题,但我当时没仔细想这个问题。
之前也没遇到过相似类型的题,而且之前周赛很少会有机会做到最后一题。。。但我注意到题目中说不得调用超过400次,而题目的数据是10^3级别的,也就是说 O ( N ) O(N) O(N)肯定是不可行的,肯定就是 log ⁡ n \log n logn相关的了,自然想到二分解法。然后就大概有思路了,一个矩形可以分成四块,对每一块用一下API,如果有,就进去递归计算。因为题目中说了不超过10艘船,所以递归的次数不会太多。边界条件是,当缩小到只有一个点的时候,API的返回值就是里面船的个数(1或0)。

class Solution {
public:
    int countShips(Sea sea, vector<int> topRight, vector<int> bottomLeft) {
        int by=topRight[1],sy=bottomLeft[1],bx=topRight[0],sx=bottomLeft[0],res=0;//表示big/small x/y。。
        if(by==sy&&bx==sx) return sea.hasShips({bx,by},{sx,sy});//边界条件
        int midx=(bx+sx)>>1,midy=(by+sy)>>1;
 //左上角
        if(midx>=sx&&by>=midy+1&&sea.hasShips({midx,by},{sx,midy+1})){
            res+=countShips(sea,{midx,by},{sx,midy+1});
        }
//右上角
        if(bx>=midx+1&&by>=midy+1&&sea.hasShips({bx,by},{midx+1,midy+1})){
            res+=countShips(sea,{bx,by},{midx+1,midy+1});
        }
//左下角
        if(midx>=sx&&midy>=sy&&sea.hasShips({midx,midy},{sx,sy})){
            res+=countShips(sea,{midx,midy},{sx,sy});
        }
//右下角
        if(bx>=midx+1&&midy>=sy&&sea.hasShips({bx,midy},{midx+1,sy})){
            res+=countShips(sea,{bx,midy},{midx+1,sy});
        }
        return res;
    }
};

第一次写题解。。还很菜

你可能感兴趣的:(【Leetcode】第14场双周赛)