来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/goal-parser-interpretation
声明:如果我侵犯了任何人的权利,请联系我,我会删除
欢迎高手来喷我
大神的代码来自 argnote,此次周赛中以java取得前五的成绩(第四),厉害了!!!!!!!!!
文章目录
5617. 设计 Goal 解析器
请你设计一个可以解释字符串 command 的 Goal 解析器 。command 由 “G”、"()" 和/或 "
(al)" 按某种顺序组成。Goal 解析器会将 “G” 解释为字符串 “G”、"()" 解释为字符串 “o” ,"(al)" 解释为字符串 “al” 。然后,按原顺序将经解释得到的字符串连接成一个字符串。
给你字符串 command ,返回 Goal 解析器 对 command 的解释结果。
示例 1:
输入:command = “G()(al)”
输出:“Goal”
解释:Goal 解析器解释命令的步骤如下所示:
G -> G
() -> o
(al) -> al
最后连接得到的结果是 “Goal”
本人的代码直接用的遍历模拟:
class Solution {
public String interpret(String command) {
char[] chs = command.toCharArray();
int len = chs.length;
int i=0;
StringBuffer sb = new StringBuffer();
while(i<len){
if(chs[i]=='('){
if(chs[i+1]=='a'){
sb.append("al");i++;i++;i++;i++;
}else if(chs[i+1]==')'){
sb.append('o');i++;
}
}else if(chs[i]=='G'){
sb.append('G');i++;
}else i++;
}
return sb.toString();
}
}
参考大神的代码,直接用replaceAll()
public String interpret(String command) {
return command.replaceAll("\\(\\)", "o").replaceAll("\\(al\\)", "al");
}
这里贴一些replaceAll的用法:
- 替换字符串中的数字:
String str = “ab123sdab4543das756as876asd”;
str = str.replaceAll("\d+", “#num#”); //"\d+",任意多个数字字符
输出:ab#num#sdab#num#das#num#as#num#asd
或者:
str = str.replaceAll("[0-9]+", “#num#”);是一样的结果 - 替换任意的非特殊字符串:
String regex = “(wqnmlgb|shuai|mei|rnmb|com|db|djb)”;
String message = “wqnmlgb!你怎么这么mei!com!你真shuai”;
message = message.replaceAll(regex, “***”);
输出:***!你怎么这么***!***!你真*** - 替换.点符号
String classFile = “com.jd.beijing”. replaceAll("\.", “") + “MyClass.class”;
输出:comjdbeijingMyClass.class
如果不加转义字符:
String classFile = “com.jd.beijing”. replaceAll(".", "”) + “MyClass.class”;
输出:**************MyClass.class - 替换 \ 字符
String str1=“aa\bbb”, str2=“aa’bbb”;
System.out.println(str1); //输出:aa\bbb
str1 = str1.replaceAll("\\", “-”);
System.out.println(str2); //输出:aa-bbb
str2 = str2.replaceAll("’", “\\”);
System.out.println(str2); //输出:aa\bbb
String 的 replaceAll() 方法,实际是采用正则表达式的规则去匹配的,\\ ,java解析为\交给正则表达式, 正则表达式再经过一次转换,把\转换成为\
5618. K 和数对的最大数目
给你一个整数数组 nums 和一个整数 k 。
每一步操作中,你需要从数组中选出和为 k 的两个整数,并将它们移出数组。
返回你可以对数组执行的最大操作数。
示例 1:
输入:nums = [1,2,3,4], k = 5
输出:2
解释:开始时 nums = [1,2,3,4]:
- 移出 1 和 4 ,之后 nums = [2,3]
- 移出 2 和 3 ,之后 nums = []
不再有和为 5 的数对,因此最多执行 2 次操作。
示例 2:
输入:nums = [3,1,3,4,3], k = 6
输出:1
解释:开始时 nums = [3,1,3,4,3]:
- 移出前两个 3 ,之后nums = [1,4,3]
不再有和为 6 的数对,因此最多执行 1 次操作。
提示:
1 <= nums.length <= 105
1 <= nums[i] <= 109
1 <= k <= 109
我自己用的模拟,
用Map<Integer, List> 来记录每个数字出现的下标list,然后遍历数组nums,找到匹配的就在list中删除,注意一下两个数字相等且相加等于K的情况,这时候只能操作一个list
public int maxOperations(int[] nums, int k) {
Map<Integer, List<Integer>> map = new HashMap<>();
//将下标存进对应的list中
for(int i=0;i<nums.length;++i){
if(!map.containsKey(nums[i])){
map.put(nums[i],new ArrayList<Integer>());
}
map.get(nums[i]).add(i);
}
int ret = 0;
for(int i=0;i<nums.length;++i){
int t = k-nums[i];
List<Integer> list = map.get(nums[i]);
//如果 k-nums[i] = nums[i],只能操作一个list两次
if(t==nums[i]){
if(list.size()>=2){
ret ++;
list.remove(list.size()-1);
list.remove(list.size()-1);
}
}else{
//否则就操作两个list,每个list都减去1
if(list.size()>0){
if(map.containsKey(t)){
List<Integer> tmp = map.get(t);
if(tmp.size()>0){
ret ++;
tmp.remove(tmp.size()-1);
list.remove(list.size()-1);
}
}
}
}
}
return ret;
}
大神的代码:
应该是相似的思路,不过没有记录下标,而是记录的数字出现的个数,
- k - num 和num不相等的话,直接把count+(num,k-num出现的次数的最小值)
- k - num 和 num相等的话,由于数成对出现,所以要count + (num出现的次数 /2),比如num=3出现的次数为4,k=6,那么k-num=num,cout + 4/2,因为(3,3),(3,3)成对
- 最后已经计数过的 num和k-num要从mao里面去掉
public int maxOperations(int[] nums, int k) {
//用map记录数字出现的个数
HashMap<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
int count = 0;
for (int num : nums) {
if (map.containsKey(num) && map.containsKey(k - num)) {
count += Math.min(map.get(num), map.get(k - num)) / (num == k - num ? 2 : 1);
map.remove(num);
map.remove(k - num);
}
}
return count;
}
5620. 连接连续二进制数字
给你一个整数 n ,请你将 1 到 n 的二进制表示连接起来,并返回连接结果对应的 十进制 数字对 10^9 + 7 取余的结果。
示例 1:
输入:n = 1
输出:1
解释:二进制的 “1” 对应着十进制的 1 。
实例 2:
输入:n = 3
输出:27
解释:二进制下,1,2 和 3 分别对应 “1” ,“10” 和 “11” 。
将它们依次连接,我们得到 “11011” ,对应着十进制的 27 。
示例 3:
输入:n = 12
输出:505379714
解释:连接结果为 “1101110010111011110001001101010111100” 。
对应的十进制数字为 118505380540 。
对 109 + 7 取余后,结果为 505379714 。
提示:
1 <= n <= 10^5
我的思路:
以3为例:n=1,2,3,
也就是1, 10,11,
分别拼接起来就是1,110,11011,
可以看出n=2时,n=1往左平移两位再加2,n=3时,n=2往左平移三位再加3,
由此看出n=N时,n=N-1需要往左平移N的(二进制的位数)位再加N…
public int concatenatedBinary(int n) {
//int bitcount = bitcount(n);
//System.out.println(bitcount);
//这里偷懒了,用long来定义ret,避免平移是产生溢出,
long ret = 1L;
for(int i=2;i<=n;++i){
int bitcount = bitcount(i);
ret = (ret << bitcount) + i;
ret = ret % 1000000007;
}
return (int)ret;
}
//n的二进制有多少位,比如n=3有3位,n=12时有4位
public int bitcount(int n){
int ret = 1;
while(n / 2 != 0){
ret++;
n /= 2;
}
return ret;
}
大神的代码 直接用的位运算,,,,位运算,,,位,,,
我还是啃了啃,妈呀,真香!!!!所以我加了点//解释
public int concatenatedBinary(int n) {
//用long是为了避免在移位的时候产生溢出的麻烦
long size = 0, result = 0;
for (int i = 1; i <= n; i++) {
//这里的(i & (i - 1)是为了计算左移的位数
//遍历到10时,因为之前是1,size=1,所以要size+1
//遍历到100时,之前是01,11,size=2,所以size+1
//1到10,位数加一, 11到100位数加一, 111到1000位数加一。。。。
if ((i & (i - 1)) == 0) {
size += 1;
}
//size计算出来之后,就是result左移size位,然后加i,这里的 | 按位或的操作相当于加法了,比如,3(11)向左移动2位后,是1100,再和2(10)或,就成了1110,相当于加法了
result = ((result << size) | i) % 1000000007;
}
return (int) result;
}
5619. 最小不兼容性(我没有做出来,题解也看不懂,只做了题目的搬运工)
给你一个整数数组 nums 和一个整数 k 。你需要将这个数组划分到 k 个相同大小的子集中,使得同一个子集里面没有两个相同的元素。
一个子集的 不兼容性 是该子集里面最大值和最小值的差。
请你返回将数组分成 k 个子集后,各子集 不兼容性 的 和 的 最小值 ,如果无法分成分成 k 个子集,返回 -1 。
子集的定义是数组中一些数字的集合,对数字顺序没有要求。
示例 1:
输入:nums = [1,2,1,4], k = 2
输出:4
解释:最优的分配是 [1,2] 和 [1,4] 。
不兼容性和为 (2-1) + (4-1) = 4 。
注意到 [1,1] 和 [2,4] 可以得到更小的和,但是第一个集合有 2 个相同的元素,所以不可行
示例 2:
输入:nums = [6,3,8,1,3,1,2,2], k = 4
输出:6
解释:最优的子集分配为 [1,2],[2,3],[6,8] 和 [1,3] 。
不兼容性和为 (2-1) + (3-2) + (8-6) + (3-1) = 6 。
示例 3:
输入:nums = [5,3,3,6,3,3], k = 3
输出:-1
解释:没办法将这些数字分配到 3 个子集且满足每个子集里没有相同数字。