每日两题
acwing
题目名
- 最大异或对
题面
在给定的 N 个整数 A1,A2……AN 中选出两个进行 xor(异或)运算,得到的结果最大是多少?
输入格式
第一行输入一个整数 N。
第二行输入 N 个整数 A1~AN。
输出格式
输出一个整数表示答案。
数据范围
1≤N≤105,
0≤Ai<231
输入样例:
3
1 2 3
输出样例:
3
分析
和昨天那题一样,都需要运用字典树。区别是,这次不是26个字母,而是0,1数字,而且为了找到最大异或结果,要将每个数都转为31位的二进制数(从最高位开始存),即son数组的第一维要变为31*N,第二维变为2。插入相同,无需记录个数。查找每个数的最大异或结果时,从跟开始找,有相反的数则沿着该分支向下,结果2再+1(即左移一位再因为成功找到异或数再加1)否则就沿着相同数都分支向下,结果2。
代码
别的不再多说,上代码:
//
// Created by ASUS on 2021/5/26.
//
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100005,M=31*N;
int son[M][2],idx;
long long a[N];
void insert(int x)
{
int p=0;
for(int i=30;i>=0;i--)
{
int u=x>>i&1;
if(!son[p][u])
son[p][u]=++idx;
p=son[p][u];
}
}
long long zuida(int x)
{
int p=0;
long long res=0;
for(int i=30;i>=0;i--)
{
int u=x>>i&1;
if(son[p][!u])
{
p=son[p][!u];
res=res*2+1;
}
else
{
p=son[p][u];
res*=2;
}
}
return res;
}
int main()
{
int n;
cin>>n;
long long res=0;
for(int i=0;i<n;i++)
{
cin>>a[i];
insert(a[i]);
}
for(int i=0;i<n;i++)
{
res=max(res,zuida(a[i]));
}
cout<<res<<endl;
return 0;
}
leetcode
题目名
- 反转每对括号间的子串
题面
给出一个字符串 s(仅含有小写英文字母和括号)。
请你按照从括号内到外的顺序,逐层反转每对匹配括号中的字符串,并返回最终的结果。
注意,您的结果中 不应 包含任何括号。
示例 1:
输入:s = “(abcd)”
输出:“dcba”
示例 2:
输入:s = “(u(love)i)”
输出:“iloveu”
示例 3:
输入:s = “(ed(et(oc))el)”
输出:“leetcode”
示例 4:
输入:s = “a(bcdefghijkl(mno)p)q”
输出:“apmnolkjihgfedcbq”
提示:
0 <= s.length <= 2000
s 中只有小写英文字母和括号
我们确保所有括号都是成对出现的
分析
终于遇到一道一眼能做的题(ORZ)。
整体是个栈的思想,遇到左括号入栈,遇到右括号,将栈顶左括号弹出,反转这对括号之间的字符串。
具体实现:
遍历字符串,定义一个一维数组zkh用来记录遇到的左括号的位置,遇到右括号则用reverse函数将这段字符串反转,zkh数组长度减一。遍历完毕后去掉原字符串中的括号即可。
代码
class Solution {
public:
string reverseParentheses(string s) {
int zkh[2000],n=0;
string res;
for(int i=0;i<s.length();i++)
{
if(s[i]=='(')
zkh[n++]=i;
if(s[i]==')') {
reverse(&s[zkh[n-1]+1], &s[i]);//reverse的两个参数一定要是地址!!!而且是左闭右开的区间!
n--;
}
}
for(int i=0;i<s.length();i++)
{
if(s[i]!='('&&s[i]!=')')//也可以通过string的erase函数(两个参数,第一个是起始位置即下标,第二个是删除的位数)将括号删除,不过需要将下标i倒回一位。最后返回原字符串s
res+=s[i];
}
return res;
}
};
acwing143题链接
link.
leetcode1190题链接
link.