Leetcode刷题 2021.02.12
Leetcode957 N 天后的牢房
8 间牢房排成一排,每间牢房不是有人住就是空着。
每天,无论牢房是被占用或空置,都会根据以下规则进行更改:
如果一间牢房的两个相邻的房间都被占用或都是空的,那么该牢房就会被占用。
否则,它就会被空置。
(请注意,由于监狱中的牢房排成一行,所以行中的第一个和最后一个房间无法有两个相邻的房间。)
我们用以下方式描述监狱的当前状态:如果第 i 间牢房被占用,则 cell[i]==1,否则 cell[i]==0。
根据监狱的初始状态,在 N 天后返回监狱的状况(和上述 N 种变化)。
看到N的大小就感觉这题肯定是会有循环的,一开始想要是一直不循环怎么办。后来看到大小一共就是8,那么不管怎么样一共可能的个数就是256个。题解好像验证了只要14次就会出现循环。
class Solution {
//需要一个set记录是否出现过,一个list,记录出现的情况
//其实感觉不需要set,只要记录第一个就行了。
Set<Integer> set = new HashSet<>();
List<int[]> list = new ArrayList<>();
public int[] prisonAfterNDays(int[] cells, int N) {
int n = cells.length;
for(int k = 0; k < N; k++){
//进行模拟
int[] res = new int[cells.length];
for(int i = 1; i < n - 1; i++){
if ((cells[i - 1] == 0 && cells[i + 1] == 0) || (cells[i - 1] == 1 && cells[i + 1] == 1)){
res[i] = 1;
}
}
// System.out.println(Arrays.toString(res));
int temp = hash(res);
//如果出现过了,就返回第(N - k - 1) % size个
if (set.contains(temp)){
int size = list.size();
return list.get((N - k - 1) % size);
}else{
//否则加入到set和list中
set.add(temp);
list.add(res);
}
for(int j = 0; j < 8; j++) cells[j] = res[j];
//如果没有出现过,又结束循环了就直接返回
if (k == N - 1) return res;
}
return new int[]{
};
}
//数组写一个hash函数
private int hash(int[] num){
int sum = 0;
for(int i = 0; i < num.length; i++){
sum += (int)Math.pow(2, i) * num[i];
}
return sum;
}
}
Leetcode991 坏了的计算器
在显示着数字的坏计算器上,我们可以执行以下两种操作:
双倍(Double):将显示屏上的数字乘 2;
递减(Decrement):将显示屏上的数字减 1 。
最初,计算器显示数字 X。
返回显示数字 Y 所需的最小操作数。
正着想不太好想,所以可以试着倒着来。因为只有乘以2,或者减1。所以如果大于目标值,就只能一直减。
倒着想如果是奇数,就不可能是一个数乘以2达到的。所以只能是减一,如果是偶数的话,就是一个数乘以2达到的。
写的有点乱,其实也不知道这个为什么是对的。可能题刷多了就自动有思路了吧。
class Solution {
public int brokenCalc(int X, int Y) {
int res = 0;
while(X < Y){
if (Y % 2 != 0){
Y++;
}else{
Y = Y/2;
}
res++;
}
res += X - Y;
return res;
}
}
Leetcode1027 最长等差数列
给定一个整数数组 A,返回 A 中最长等差子序列的长度。
回想一下,A 的子序列是列表 A[i_1], A[i_2], …, A[i_k] 其中 0 <= i_1 < i_2 < … < i_k <= A.length - 1。并且如果 B[i+1] - B[i]( 0 <= i < B.length - 1) 的值都相同,那么序列 B 是等差的。
基本的动态规划题,用HashMap作为dp数组,可以用整形数组,提升效率。
class Solution {
public int longestArithSeqLength(int[] A) {
int n = A.length;
Map<Integer, Integer>[] map = new Map[n];
for(int i = 0; i < n; i++){
map[i] = new HashMap<>();
}
for(int i = 0; i < n; i++){
for(int j = 0; j < i; j++){
int diff = A[i] - A[j];
//如果之前的元素没有递增序列或者,该差值不存在
if (map[j].size() == 0 || !map[j].containsKey(diff)){
//就加入差值,初始化为2
map[i].put(diff, 2);
}else if (map[j].containsKey(diff)){
//如果该元素有这个差值,更新一下最大值
if (map[i].containsKey(diff)){
if (map[j].get(diff) + 1 > map[i].get(diff)){
map[i].put(diff, map[j].get(diff) + 1);
}
}else{
//否则也直接加入之前的最大长度+1
map[i].put(diff, map[j].get(diff) + 1);
}
}
}
}
//遍历一遍取最大值
int res = 0;
for(int i = 0; i < map.length; i++){
for(Integer key : map[i].keySet()){
res = Math.max(res, map[i].get(key));
}
}
return res;
}
}