leetcode
每日一题
有效括号的嵌套深度
// 1111.有效括号的嵌套深度
/*
有效括号字符串 定义:对于每个左括号,都能找到与之对应的右括号,反之亦然。详情参见题末「有效括号字符串」部分。
嵌套深度 depth 定义:即有效括号字符串嵌套的层数,depth(A) 表示有效括号字符串 A 的嵌套深度。详情参见题末「嵌套深度」部分。
给你一个「有效括号字符串」 seq,请你将其分成两个不相交的有效括号字符串,A 和 B,并使这两个字符串的深度最小。
不相交:每个 seq[i] 只能分给 A 和 B 二者中的一个,不能既属于 A 也属于 B 。
A 或 B 中的元素在原字符串中可以不连续。
A.length + B.length = seq.length
深度最小:max(depth(A), depth(B)) 的可能取值最小。
划分方案用一个长度为 seq.length 的答案数组 answer 表示,编码规则如下:
answer[i] = 0,seq[i] 分给 A 。
answer[i] = 1,seq[i] 分给 B 。
*/
public class Demo10 {
public int[] maxDepthAfterSplit(String seq) {
int[] ans=new int[seq.length()];
int tmp=0;
//解题思路,如果连续出现两个'('则可以放进不同的栈里面,可以理解为把奇数位的给一个栈,剩下的给来一个栈,如果出现了')'则把它偶数位的给奇数位的'(',
for (char c:seq.toCharArray()){
ans[tmp++]=c=='('?tmp&1:(tmp+1)&1;
}
return ans;
}
}
最大矩形面积
package leetcode;
/*
给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。
示例:
输入:
[
["1","0","1","0","0"],
["1","0","1","1","1"],
["1","1","1","1","1"],
["1","0","0","1","0"]
]
输出: 6
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximal-rectangle
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
public class Demo11 {
public static void main(String[] args) {
char[][] b={
{1,0,1,0,0},
{1,0,1,1,1},
{1,1,1,1,1},
{1,0,0,1,0}
};
System.out.println(maximalRectangle(b));
}
public static int maximalRectangle(char[][] matrix) {
int max=0;
int a = matrix.length;
int b = matrix[0].length;
int[][] len=new int[matrix.length][matrix[0].length];
for (int i=0;i<a;i++){
for (int j=0;j<b;j++){
len[i][j]=0;
}
}
for (int i=0;i<a;i++){
for (int j=0;j<b;j++){
System.out.print(len[i][j]+" ");
}
System.out.println();
}
//把每行的长度记录在二维数组中,长度为当前元素到左边最长的长度
for (int i=0;i<a;i++){
for (int j=0;j<b;j++){
if (matrix[i][j]==0){
}else{
if(j==0){
if(matrix[i][j]==1)
len[i][j]=1;
if(matrix[i][j]==0)len[i][j]=0;
}
else{len[i][j]=len[i][j-1]+1;}
}
}
}
for (int i=0;i<a;i++){
for (int j=0;j<b;j++){
System.out.print(len[i][j]+" ");
}
System.out.println();
}
for (int i=1;i<a;i++){
for (int j=1;j<b;j++){
if (len[i][j]==0)continue;
int up=i-1;
int high=1;
int length=0;
length=len[i][j];
while (up>=0&&len[up][j]!=0){
high++;
length=Math.min(length,len[up][j]);
max=Math.max(Math.max(len[i][j],max),(length*high));
up--;
}
}
}
return max;
}
}
字符串转换整数(考虑int边界)
package leetcode;
//请你来实现一个 atoi 函数,使其能将字符串转换成整数。
//
// 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。接下来的转化规则如下:
//
//
// 如果第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字字符组合起来,形成一个有符号整数。
// 假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成一个整数。
// 该字符串在有效的整数部分之后也可能会存在多余的字符,那么这些字符可以被忽略,它们对函数不应该造成影响。
//
//
// 注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换,即无法进行有效转换。
//
// 在任何情况下,若函数不能进行有效的转换时,请返回 0 。
//
// 提示:
//
//
// 本题中的空白字符只包括空格字符 ' ' 。
// 假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231
// − 1) 或 INT_MIN (−231) 。
//
//
//
//
// 示例 1:
//
// 输入: "42"
//输出: 42
//
//
// 示例 2:
//
// 输入: " -42"
//输出: -42
//解释: 第一个非空白字符为 '-', 它是一个负号。
// 我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
//
//
// 示例 3:
//
// 输入: "4193 with words"
//输出: 4193
//解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。
//
//
// 示例 4:
//
// 输入: "words and 987"
//输出: 0
//解释: 第一个非空字符是 'w', 但它不是数字或正、负号。
// 因此无法执行有效的转换。
//
// 示例 5:
//
// 输入: "-91283472332"
//输出: -2147483648
//解释: 数字 "-91283472332" 超过 32 位有符号整数范围。
// 因此返回 INT_MIN (−231) 。
//
// Related Topics 数学 字符串
public class Demo12 {
public static int myAtoi(String str) {
int a=0;//作为空格的指针
int ans=0;
char[] chars = str.toCharArray();
if (chars.length==0){return 0;}
while (a<chars.length&&chars[a]==' '){
a++;
}
//判断第一个符号是否是’-‘,’+‘。
boolean negative=false;//出现负号则为true
if (a<chars.length&&chars[a]=='-'){
negative=true;
a++;
}else if (a<chars.length&&chars[a]=='+'){
negative=false;
a++;
}else if (a<chars.length&&!Character.isDigit(chars[a])){
return 0;
}
//Class Character.isDigit(char ch)
while (a<chars.length) {
if (Character.isDigit(chars[a])){
//判断是否超过INTEGER.MAX_VALUE或者INTEGER.MIN_VALUE
if(!negative&&ans>(Integer.MAX_VALUE-chars[a]+'0')/10){
return Integer.MAX_VALUE;
}
if (negative&&-ans<(Integer.MIN_VALUE+chars[a]-'0')/10){
return Integer.MIN_VALUE;
}
ans=ans*10+chars[a]-'0';
a++;
}else{break;}//数字后出现了其他的字符,则终止循环
}
return negative?-ans:ans;
}
}
生命游戏
package leetcode;
//根据 百度百科 ,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。
//
// 给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态:1 即为活细胞(live),或 0 即为死细胞(dea
//d)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:
//
//
// 如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
// 如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
// 如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
// 如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
//
//
// 根据当前状态,写一个函数来计算面板上所有细胞的下一个(一次更新后的)状态。下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生
//和死亡是同时发生的。
//
//
//
// 示例:
//
// 输入:
//[
// [0,1,0],
// [0,0,1],
// [1,1,1],
// [0,0,0]
//]
//输出:
//[
// [0,0,0],
// [1,0,1],
// [0,1,1],
// [0,1,0]
//]
//
//
//
// 进阶:
//
//
// 你可以使用原地算法解决本题吗?请注意,面板上所有格子需要同时被更新:你不能先更新某些格子,然后使用它们的更新后的值再更新其他格子。
// 本题中,我们使用二维数组来表示面板。原则上,面板是无限的,但当活细胞侵占了面板边界时会造成问题。你将如何解决这些问题?
//
// Related Topics 数组
//leetcode submit region begin(Prohibit modification and deletion)
class Demo13 {
public void gameOfLife(int[][] board) {
int[] x={-1,0,1,-1,1,-1,0,1};
int[] y={-1,-1,-1,0,0,1,1,1};//用两个数组记录八个方向
//如果没有元素则停止方法
if (board.length==0){return;}
int a=board.length;//宽度
int b=board[0].length;//长度
//思路:因为细胞的状态0和1在内存中只占一位,所以只需在内存的上一位中存储下一次状态即可节省空间
for (int i=0;i<a;i++){
for (int j=0;j<b;j++){//两个for遍历每一个细胞
int cnt=0;//记录每一个细胞的八个方向的细胞数
for (int k=0;k<8;k++){//遍历每一个细胞的八个方向
int newX=x[k]+j;
int newY=y[k]+i;
if (newX<0||newX>=b||newY<0||newY>=a)continue;
cnt+=board[newY][newX]&1;//因为数组可能已经被运算了,所有要进行位运算
}
// 如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
// 如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
// 如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
if ((board[i][j]&1)>0){
if (cnt==3||cnt==2) {board[i][j]=0b11;}
// else if (cnt==2||cnt==3)board[i][j]=0b01;
// else if (cnt<2)board[i][j]=0b01;
}else if (cnt==3){// 如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
board[i][j]=0b10;
}
}
}
//将数组的状态转换为下一个状态
for (int i=0;i<a;i++){
for (int j=0;j<b;j++){
board[i][j]>>=1;
}
}
}
}
//leetcode submit region end(Prohibit modification and deletion)