LeetCode 1185. 一周中的第几天 / 913. 猫和老鼠(博弈,动态规划) / 1576. 替换所有的问号
作者:互联网
1185. 一周中的第几天
2021.1.3 每日一题
题目描述
给你一个日期,请你设计一个算法来判断它是对应一周中的哪一天。
输入为三个整数:day、month 和 year,分别表示日、月、年。
您返回的结果必须是这几个值中的一个 {“Sunday”, “Monday”, “Tuesday”, “Wednesday”, “Thursday”, “Friday”, “Saturday”}。
示例 1:
输入:day = 31, month = 8, year = 2019
输出:“Saturday”
示例 2:
输入:day = 18, month = 7, year = 1999
输出:“Sunday”
示例 3:
输入:day = 15, month = 8, year = 1993
输出:“Sunday”
提示:
给出的日期一定是在 1971 到 2100 年之间的有效日期。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/day-of-the-week
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
先输入个例子,看1971年1月1日是星期几,然后再根据这个基数计算其他天数是星期几
class Solution {
static String[] week = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
static int[] monthday = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
public String dayOfTheWeek(int day, int month, int year) {
//肯定得有个基数开始算,例如知道1971年1月1日是星期几
//看了题解,是星期五,那么计算当前日期与该日期的天数差就可以了
//和那天计算多少天一样
//先计算年份
int temp = 365 * (year - 1971);
//加上闰年的个数,例如1972年,就加1
//因为最多是2100年,所以没有判断世纪闰年
temp += (year - 1969) / 4;
//计算月份
for(int i = 0; i < month - 1; i++){
temp += monthday[i];
}
//判断当前年份是否是闰年
if((year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) && month > 2)
temp++;
temp += day;
//System.out.println(temp);
int idx = (temp % 7 + 4) % 7;
return week[idx];
}
}
913. 猫和老鼠
2021.1.4 每日一题
题目描述
两位玩家分别扮演猫和老鼠,在一张 无向 图上进行游戏,两人轮流行动。
图的形式是:graph[a] 是一个列表,由满足 ab 是图中的一条边的所有节点 b 组成。
老鼠从节点 1 开始,第一个出发;猫从节点 2 开始,第二个出发。在节点 0 处有一个洞。
在每个玩家的行动中,他们 必须 沿着图中与所在当前位置连通的一条边移动。例如,如果老鼠在节点 1 ,那么它必须移动到 graph[1] 中的任一节点。
此外,猫无法移动到洞中(节点 0)。
然后,游戏在出现以下三种情形之一时结束:
如果猫和老鼠出现在同一个节点,猫获胜。
如果老鼠到达洞中,老鼠获胜。
如果某一位置重复出现(即,玩家的位置和移动顺序都与上一次行动相同),游戏平局。
给你一张图 graph ,并假设两位玩家都都以最佳状态参与游戏:
如果老鼠获胜,则返回 1;
如果猫获胜,则返回 2;
如果平局,则返回 0 。
示例 1:
输入:graph = [[2,5],[3],[0,4,5],[1,4,5],[2,3],[0,2,3]]
输出:0
示例 2:
输入:graph = [[1,3],[0],[3],[0,2]]
输出:1
提示:
3 <= graph.length <= 50
1 <= graph[i].length < graph.length
0 <= graph[i][j] < graph.length
graph[i][j] != i
graph[i] 互不相同
猫和老鼠在游戏中总是移动
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/cat-and-mouse
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
按照下面思路写的代码,然后倒在了[[2,3],[3,4],[0,4],[0,1],[1,2]]这个例子上
这个例子中,按照我的代码,老鼠有可能被抓住,也有可能进洞,所以结果就是平局,但是实际上老鼠肯定比猫先进洞,所以是1
但是这个情况怎么考虑呢,考虑与0的距离吗,也不太行啊
class Solution {
int[][] used;
int[][] graph;
public int catMouseGame(int[][] graph) {
//老鼠肯定想往洞靠近,但是不能走猫的路线,但是怎么保证是走的最优路线呢
//而猫呢,是想抓老鼠,但是如果都走一步的情况下,除非是死胡同,猫才能获胜,否则最多平局
//可以用递归的方式进行模拟,如果说猫怎么走都能抓住老鼠,或者老鼠怎么走都能进洞是两种特殊情况
//否则都是平局
//另外,如果2不能走到1,那么就是老鼠赢,如果老鼠比猫离的0近,那么老鼠赢
//如果猫怎么走,老鼠都能进洞,那么就是老鼠赢,如果老鼠怎么走,都要被抓住就是猫赢
//其他情况就是平局
//先写个深度优先看看
this.graph = graph;
int l = graph.length;
used = new int[l][l];
for(int[] t : used){
Arrays.fill(t, -1);
}
return helper(2, 1);
}
//猫的位置和鼠的位置,上一步猫和老鼠的位置
public int helper(int posc, int posm){
//如果此时鼠的位置在0,那么老鼠获胜
if(posm == 0)
return 1;
//如果此时鼠的位置只能走到猫的位置,那么猫获胜
if(graph[posm].length == 1 && graph[posm][0] == posc)
return 2;
int[] tempm = graph[posm];
int[] tempc = graph[posc];
boolean catwin = false;
boolean mousewin = false;
//遍历所有老鼠下一步的位置,如果所有老鼠的位置都返回1,那么才是1
//如果都返回2,那么才是2,如果有1有2,那么就是0
//表示当前位置正在遍历
used[posm][posc] = 3;
for(int nextm : tempm){
//如果老鼠的下一个位置是0,那么就返回1
if(nextm == 0) {
mousewin = true;
break;
}
//遍历所有猫的位置
for(int nextc : tempc){
//如果猫到了0位置,说明此路不通
if(nextc == 0)
continue;
//如果猫走到了老鼠的位置,说明肯定能抓到
if(nextc == nextm){
catwin = true;
continue;
}
if(used[nextm][nextc] != -1){
//如果当前位置正在被遍历,那么就跳过这个位置
if(used[nextm][nextc] == 3){
continue;
}
else if(used[nextm][nextc] == 1){
mousewin = true;
}
else if(used[posm][posc] == 2){
catwin = true;
}else{
used[posm][posc] = 0;
return 0;
}
}
int t = helper(nextc, nextm);
//如果老鼠能赢
if(t == 1)
mousewin = true;
//如果猫能赢
if(t == 2)
catwin = true;
}
}
if(catwin && !mousewin)
used[posm][posc] = 2;
else if(mousewin && !catwin)
used[posm][posc] = 1;
else
used[posm][posc] = 0;
return used[posm][posc];
}
}
看了题解,竟然需要再加上一个轮次的维度才能表示正确结果
对于老鼠来说,如果能走到0,其实就赢了,因为默认猫采取的也是最优策略
同理,对于猫来说,抓住老鼠,也就赢了
class Solution {
int[][][] used;
int[][] graph;
int l;
public int catMouseGame(int[][] graph) {
//老鼠肯定想往洞靠近,但是不能走猫的路线,但是怎么保证是走的最优路线呢
//而猫呢,是想抓老鼠,但是如果都走一步的情况下,除非是死胡同,猫才能获胜,否则最多平局
//可以用递归的方式进行模拟,如果说猫怎么走都能抓住老鼠,或者老鼠怎么走都能进洞是两种特殊情况
//否则都是平局
//另外,如果2不能走到1,那么就是老鼠赢,如果老鼠比猫离的0近,那么老鼠赢
//如果猫怎么走,老鼠都能进洞,那么就是老鼠赢,如果老鼠怎么走,都要被抓住就是猫赢
//其他情况就是平局
//先写个深度优先看看
this.graph = graph;
l = graph.length;
used = new int[l][l][2 * l];
for(int[][] t : used){
for(int[] tt : t){
Arrays.fill(tt, -1);
}
}
return helper(2, 1, 0);
}
//猫的位置和鼠的位置,当前轮次
//返回值表示当前轮次,猫和老鼠在当前位置最后的胜利者
public int helper(int posc, int posm, int k){
//如果走过一轮了,还没有分出胜负,那么返回0
if(k >= 2 * l)
return 0;
//如果此时鼠的位置在0,那么老鼠获胜
if(posm == 0)
return used[posm][posc][k] = 1;
//如果猫在老鼠的位置,那么猫获胜
if(posc == posm)
return used[posm][posc][k] = 2;
if(used[posm][posc][k] != -1)
return used[posm][posc][k];
int[] tempm = graph[posm];
int[] tempc = graph[posc];
//当前正在老鼠的回合,对于老鼠来说,如果能走到0,那么就赢了,因为猫使用的也是最优策略
if(k % 2 == 0){
int res = 2;
for(int next : tempm){
int ans = helper(posc, next, k + 1);
//如果老鼠能赢的话,那么就返回老鼠赢
if(ans == 1)
return used[posm][posc][k] = 1;
if(ans == 0)
res = 0;
}
return used[posm][posc][k] = res;
//当前猫的回合,对于猫来说,如果抓住老鼠,那么就赢了,因为老鼠也使用的是最优策略
}else{
int res = 1;
for(int next : tempc){
if(next == 0)
continue;
int ans = helper(next, posm, k + 1);
if(ans == 2)
return used[posm][posc][k] = 2;
if(ans == 0)
res = 0;
}
return used[posm][posc][k] = res;
}
}
}
再次看博弈这道题,就是分两个人的动作,也就是分两个人考虑,按照轮次来依次进行操作,如果轮次超过了2k,说明在最优策略下,两个人已经走过了一轮,所以就是平局
而我想的并没有考虑轮次的情况,而是直接判断如何获胜或者失败,相当于不是在博弈
还有看到的另一种解法是极大极小的做法,其实和这个道理上是一样的,只不过这种做法是将两个人的视角变成一个人的视角了
1576. 替换所有的问号
2021.1.5 每日一题
题目描述
给你一个仅包含小写英文字母和 ‘?’ 字符的字符串 s,请你将所有的 ‘?’ 转换为若干小写字母,使最终的字符串不包含任何 连续重复 的字符。
注意:你 不能 修改非 ‘?’ 字符。
题目测试用例保证 除 ‘?’ 字符 之外,不存在连续重复的字符。
在完成所有转换(可能无需转换)后返回最终的字符串。如果有多个解决方案,请返回其中任何一个。可以证明,在给定的约束条件下,答案总是存在的。
示例 1:
输入:s = “?zs”
输出:“azs”
解释:该示例共有 25 种解决方案,从 “azs” 到 “yzs” 都是符合题目要求的。只有 “z” 是无效的修改,因为字符串 “zzs” 中有连续重复的两个 ‘z’ 。
示例 2:
输入:s = “ubv?w”
输出:“ubvaw”
解释:该示例共有 24 种解决方案,只有替换成 “v” 和 “w” 不符合题目要求。因为 “ubvvw” 和 “ubvww” 都包含连续重复的字符。
示例 3:
输入:s = “j?qg??b”
输出:“jaqgacb”
示例 4:
输入:s = “??yw?ipkj?”
输出:“acywaipkja”
提示:
1 <= s.length <= 100
s 仅包含小写英文字母和 ‘?’ 字符
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/replace-all-s-to-avoid-consecutive-repeating-characters
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
判断是不是ab就行了,其他不用看,不过去看看题解还有什么更好的方法
好像都跟我的差不多哎,只不过是把判断三个字母写成循环的形式了
class Solution {
public String modifyString(String s) {
//其实就判断三个字符有没有就行了
int l = s.length();
char[] cc = s.toCharArray();
for(int i = 0; i < l; i++){
char c = cc[i];
if(c != '?')
continue;
boolean isa = false, isb = false;
char last = i > 0 ? cc[i - 1] : ' ';
char next = i < l - 1 ? cc[i + 1] : ' ';
if(last == 'a' || next == 'a')
isa = true;
if(last == 'b' || next == 'b')
isb = true;
if(isa && isb)
cc[i] = 'c';
else if(isa && !isb)
cc[i] = 'b';
else if(!isa && isb)
cc[i] = 'a';
else
cc[i] = 'a';
}
return new String(cc);
}
}
标签:老鼠,posm,第几天,int,graph,1185,posc,used,猫和老鼠 来源: https://blog.csdn.net/windyjcy/article/details/122297622