难度不大,本菜平时勉强三题水平,这次一小时a了。没有特别难的题,基本上一题题慢慢做就可以了。最后一题这次想到了也不难。因为以往只有会员才能看双周赛题,所以记录一下。贴的代码都是比赛时写的,很朴素的方法,肯定有更好的解法,欢迎指正。
你有⼀个⼗进制数字,请按照此规则将它变成「⼗六进制魔术数字」:⾸先将它变成字⺟⼤写的⼗六进制字符
串,然后将所有的数字 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;
}
};
给你⼀个 有序的 不相交区间列表 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;
}
};
给你⼀棵以节点 L 为根节点的树,定义如下:
节点的总数为 nodes 个;
第 i 个节点的值为 value[i] ;
第 i 个节点的⽗节点是 parent[i] 。
请你删除节点值之和为 L 的每⼀棵⼦树。
在完成所有删除之后,返回树中剩余节点的数⽬。
输⼊: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;
}
};
在用笛卡尔坐标系表示的二维海平面上,有一些船。每一艘船都在一个整数点上,且每一个整数点最多只有 1 艘船。
有一个函数 Sea.hasShips(topRight, bottomLeft) ,输入参数为右上角和左下角两个点的坐标,当且仅当这两个点所表示的矩形区域(包含边界)内至少有一艘船时,这个函数才返回 true ,否则返回 false 。
给你矩形的右上角 topRight 和左下角 bottomLeft 的坐标,请你返回此矩形内船只的数目。题目保证矩形内 至多只有 10 艘船。
调用函数 hasShips 超过400次 的提交将被判为 错误答案(Wrong Answer) 。同时,任何尝试绕过评测系统的行为都将被取消比赛资格。
示例:
输入:
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;
}
};
第一次写题解。。还很菜