时间:2020/02/19 十点半-十二点。只a了第一题,第二题写了一半,去吃饭了。
难度:easy,链接:https://leetcode-cn.com/problems/reformat-the-string/
给你一个混合了数字和字母的字符串 s,其中的字母均为小写英文字母。
请你将该字符串重新格式化,使得任意两个相邻字符的类型都不同。也就是说,字母后面应该跟着数字,而数字后面应该跟着字母。
请你返回 重新格式化后 的字符串;如果无法按要求重新格式化,则返回一个 空字符串 。
输入:s = "a0b1c2"
输出:"0a1b2c"
解释:"0a1b2c" 中任意两个相邻字符的类型都不同。 "a0b1c2", "0a1b2c", "0c2a1b" 也是满足题目要求的答案。
我的思路要使相邻字符类型不同,那么两个类型的字符数量差不能多于1个,所以我将这个字符串拆成两个String来存储,用String的长度来判断是否符合要求,符合要求后,每次一边取一个字符出来,最终拼接成结果。因为java中String拼接会创建新对象,所以我用StringBuilder代替了String,以减少性能消耗。
比如输入"a0b1c2",拆成"abc"和"012",长度为3和3,满足条件,从两边轮流取,从"abc"中取出a,从"012"中取出0,再从"bc"中取出b,从"12"中取出1,最后从"c"中取出c,从"2"中取出2,结果为"a0b1c2";
class Solution {
public String reformat(String s) {
StringBuilder digit = new StringBuilder();
StringBuilder character = new StringBuilder();
StringBuilder res = new StringBuilder();
for (int i = 0; i < s.length(); i++)
{
if (s.charAt(i) <= 'z' && s.charAt(i) >= 'a')
{
character.append(s.charAt(i));
}
else
{
digit.append(s.charAt(i));
}
}
int len1 = digit.length();
int len2 = character.length();
if (len1 == len2 + 1 || len1 == len2)
{
int index1 = 0;
int index2 = 0;
while (index1 < len1 && index2 < len2)
{
res.append(digit.charAt(index1++));
res.append(character.charAt(index2++));
}
if (index1 < len1) res.append(digit.charAt(index1));
}
else if(len2 == len1 + 1)
{
int index1 = 0;
int index2 = 0;
while (index1 < len1 && index2 < len2)
{
res.append(character.charAt(index2++));
res.append(digit.charAt(index1++));
}
if (index2 < len2) res.append(character.charAt(index2));
}
return res.toString();
}
}
难度:medium 链接:https://leetcode-cn.com/problems/display-table-of-food-orders-in-a-restaurant/
给你一个数组 orders,表示客户在餐厅中完成的订单,确切地说, orders[i]=[customerNamei,tableNumberi,foodItemi] ,其中 customerNamei 是客户的姓名,tableNumberi 是客户所在餐桌的桌号,而 foodItemi 是客户点的餐品名称。
请你返回该餐厅的 点菜展示表 。在这张表中,表中第一行为标题,其第一列为餐桌桌号 “Table” ,后面每一列都是按字母顺序排列的餐品名称。接下来每一行中的项则表示每张餐桌订购的相应餐品数量,第一列应当填对应的桌号,后面依次填写下单的餐品数量。
注意:客户姓名不是点菜展示表的一部分。此外,表中的数据行应该按餐桌桌号升序排列。
输入:orders = [["David","3","Ceviche"],["Corina","10","Beef Burrito"],["David","3","Fried Chicken"],["Carla","5","Water"],["Carla","5","Ceviche"],["Rous","3","Ceviche"]]
输出:[["Table","Beef Burrito","Ceviche","Fried Chicken","Water"],["3","0","2","1","0"],["5","0","1","0","1"],["10","1","0","0","0"]]
解释:
点菜展示表如下所示:
Table,Beef Burrito,Ceviche,Fried Chicken,Water
3 ,0 ,2 ,1 ,0
5 ,0 ,1 ,0 ,1
10 ,1 ,0 ,0 ,0
对于餐桌 3:David 点了 "Ceviche" 和 "Fried Chicken",而 Rous 点了 "Ceviche"
而餐桌 5:Carla 点了 "Water" 和 "Ceviche"
餐桌 10:Corina 点了 "Beef Burrito"
这道题目周赛没写完,写完了有个bug就去吃饭了,回来后改完bug就a了,难度是medium,虽然不难,但得用map套map来解决,还是挺复杂的。用一个<桌号,<这桌点的菜,点的菜的数量>>map来存储每一周点的菜,用一个Set存储出现过的菜,因为结果里面没有点的菜也得放到结果中(为0),最后用Set来组成字段(结果表格的属性行,需要排序),用map来完成每一行(需要按桌号排序),最后返回结果。
class Solution {
public List> displayTable(List> orders) {
int ordernum = orders.size();
List> res = new ArrayList();
HashSet fooditems = new HashSet();//存放菜名的set
HashMap> ordermap = new HashMap();//map,key = 桌号,value = <菜名,点的数量>
for (int i = 0; i < ordernum; i++)//读取订单
{
List order = orders.get(i);//第i个订单
HashMap map = ordermap.getOrDefault(order.get(1),new HashMap());
map.put(order.get(2), map.getOrDefault(order.get(2),0) + 1);
ordermap.put(order.get(1),map);
fooditems.add(order.get(2));
}
ArrayList foods = new ArrayList<>(fooditems);
Collections.sort(foods);//将菜名排序
for (Map.Entry> entry: ordermap.entrySet())
{
String tableid = entry.getKey();
HashMap value = entry.getValue();
ArrayList newvalue = new ArrayList();
newvalue.add(tableid);
for (int i = 0; i < foods.size(); i++)
{
newvalue.add(String.valueOf(value.getOrDefault(foods.get(i),0)));
}
res.add(newvalue);
}
Collections.sort(res,(a,b) -> (Integer.valueOf(a.get(0)) - Integer.valueOf(b.get(0)) ));//按桌号排序
foods.add(0,"Table");
res.add(0,foods);
return res;
}
}
难度:medium 链接:https://leetcode-cn.com/problems/minimum-number-of-frogs-croaking/
给你一个字符串 croakOfFrogs,它表示不同青蛙发出的蛙鸣声(字符串 "croak" )的组合。由于同一时间可以有多只青蛙呱呱作响,所以 croakOfFrogs 中会混合多个 “croak” 。请你返回模拟字符串中所有蛙鸣所需不同青蛙的最少数目。
注意:要想发出蛙鸣 "croak",青蛙必须 依序 输出 ‘c’, ’r’, ’o’, ’a’, ’k’ 这 5 个字母。如果没有输出全部五个字母,那么它就不会发出声音。
如果字符串 croakOfFrogs 不是由若干有效的 "croak" 字符混合而成,请返回 -1 。
输入:croakOfFrogs = "croakcroak" 输出:1 解释:一只青蛙 “呱呱” 两次
思路:
因为一只青蛙必须按顺序输出croak五个字母,才能输出下一个。
所以有两种情况,如果一只青蛙读完cro,又来一个c,那么就需要另一只青蛙。
如果一直青蛙读完cro,又来一个r,而因为没有读完c没读r的青蛙,所以不存在结果。
所以我们可以用c,r,o,a,k五个变量来存储读到c,读到r,读到o,读到a,读到k的青蛙数。
如果读到c,那就直接c++,读到r,需要判断是否有读到c的青蛙,如果有,即(c!=0),那么就可以继续读,c--,r++,如果c==0,即不存在读到c的青蛙,那就发生了错误,结果返回-1,读到o,a,k类似。
而当没有发生错误时,需要的青蛙数等于所有青蛙的和(c+r+o+a+k),因为和会变,结果就是所有青蛙的和的最大值。
最后也要检测是否所有的青蛙数是否都读完了,如果有青蛙没读完,那也要返回-1.
class Solution {
public int minNumberOfFrogs(String croakOfFrogs) {
int c = 0,r = 0, o = 0, a = 0, k = 0;//存储读到某个字母的青蛙个数
int sum = 0;//当前所需的青蛙数
int res = 0;//最终需要的青蛙数,即max(sum);
for (int i = 0; i < croakOfFrogs.length(); i++)
{
char temp = croakOfFrogs.charAt(i);
if (temp == 'c') //如果读到c,因为只有读到c才可能需要新青蛙,计算一下sum,更新一下res
{
c++;
sum++;
res = Math.max(sum,res);
}
else if (temp == 'r')//如果读到r,而没有读到的青蛙,那么显然出错了,将res置为1,break
{
if (c == 0)
{
res = -1;
break;
}
else
{
c--;
r++;
}
}
else if (temp == 'o')
{
if (r == 0)
{
res = -1;
break;
}
else
{
r--;
o++;
}
}
else if (temp == 'a')
{
if (o == 0)
{
res = -1;
break;
}
else
{
o--;
a++;
}
}
else
{
if (a == 0)
{
res = -1;
break;
}
else
{
a--;
k++;
sum--;
}
}
}
if (sum != 0) res = -1;//如果有青蛙没读完,那么也出错了,返回-1;
return res;
}
}
难度:hard,链接:https://leetcode-cn.com/problems/build-array-where-you-can-find-the-maximum-exactly-k-comparisons/
给你三个整数 n、m 和 k 。下图描述的算法用于找出正整数数组中最大的元素。
请你生成一个具有下述属性的数组 arr :
arr 中有 n 个整数。
1 <= arr[i] <= m 其中 (0 <= i < n) 。
将上面提到的算法应用于 arr ,search_cost 的值等于 k 。返回上述条件下生成数组 arr 的 方法数 ,由于答案可能会很大,所以 必须 对 10^9 + 7 取余。
输入:n = 2, m = 3, k = 1
输出:6
解释:可能的数组分别为 [1, 1], [2, 1], [2, 2], [3, 1], [3, 2] [3, 3]
输入:n = 5, m = 2, k = 3 输出:0 解释:没有数组可以满足上述条件
这道题目可以用三维dp来解决,dp[i][j][t] = 长度为i的数组, 最大值是t - 1,还剩下j次serach_cost增加机会的方法数
dp[i][j][t] = dp[i-1][j+1][p] + (t+1)*dp[i-1][j][t];
代码如下:
class Solution {
public int numOfArrays(int n, int m, int k) {
long[][][] dp = new long[n][k + 1][m];//dp[i][j][t] = 长度为i的数组, 最大值是t - 1,还剩下j次serach_cost增加机会的方法数
for (int i = 0; i < m; i++)
{
dp[0][k-1][i] = 1;
}
for (int i = 1; i < n; i++)
{
for (int j = 0; j < k + 1 ; j++)
{
for (int t = 0; t < m; t++)
{
for (int p = 0; p < t; p++)
{
if (j != k ) dp[i][j][t] += dp[i-1][j+1][p] ;//第i个数比之前的最大值要大
}
dp[i][j][t] += (t + 1) * dp[i-1][j][t];//第i个数比之前的最大值要小于等于
dp[i][j][t] %= 1000000007;
}
}
}
long res = 0;
for (int i = 0; i < m; i++)
{
res += dp[n-1][0][i] ;
}
res %= 1000000007;
return (int)res;
}
}