目录
LeetCode76
思路
首先要把目标字符串t转换为hash表t_hash存储,方便以后的处理,t的长度为total 。这个total很重要。然后定义两个指针i和j,j是左边的指针,i是右边的指针。j和i之间的字符就是包含t的子字符。
然后,用i开始遍历s字符串,遍历时如果该字符在t_hash中的值不为0,则说明该字符是目标字符,total--,并且t_hash的值--,说明该字符已经被取走了,如果不是t_hash的值也--,为了区分目标字符和非目标字符,在把所有目标字符都找到后,i和j中间的字符在t_hash有两种值,一个是大于等于0,一个是小于0,小于0的时非目标字符。此时已经把所有目标字符找到了,total也是0了,然后开始缩小范围,j要出场了。
当total==0时,也就是所有目标字符都有了,开始缩小范围,让左指针j向右移动,在移动前先记录下i和j之间的距离min,每次移动j都记录距离min,然后min取最小的,用left记录左指针的位置,为了返回结果,代码中的min=i-j+1,+1是为了substring的时候方便。
正式开始移动j,移动前,先把t_hash的值+1,说明结果集中没有该元素,比较当前j位置的字符在t_hash的值是不是>0,大于0说明该字符是目标字符,移动j的话total还缺少一个,让total+1,否则就是非必要字符,直接继续移动。知道total>0结束。
这里的total+1是可以确定需要哪个元素的,因为必要元素此时再t_hash表中的值已经+1了,和初始化t_hash后是一样的方法了。
代码
class Solution {
public String minWindow(String s, String t) {
if(s.length()<t.length()){
return "";
}
int[] t_hash = new int[128];
int minLength = Integer.MAX_VALUE;
int total = t.length();
int left = 0;
for(char i:t.toCharArray()){
t_hash[i]++;
}
//i是右边界,j是左边界
for(int i =0,j = 0;i<s.length();i++){
if(t_hash[s.charAt(i)] > 0){
total--;
}
t_hash[s.charAt(i)]--;
while(total == 0){
if(i-j+1<minLength){
minLength = i-j+1;
left = j;
}
t_hash[s.charAt(j)]++;
if(t_hash[s.charAt(j)] > 0){
total++;
}
j++;
}
}
return minLength == Integer.MAX_VALUE ? "":s.substring(left,left+minLength);
}
}
LeetCode79
思路
这道题可以使用回溯的方法来解决。
1.回溯终止条件
当下标index到达word的末尾时,就会结束,当i和j溢出边界时,就返回false。
2.回溯处理
每次判断board[i][j] == word.charAt(index++)时候相等,不相等就直接返回false;相等就进行处理,让当前board[i][j]='#',说明,当前元素使用过了,然后去判断上下左右四个方位是否有未使用的元素,然后回溯回来后,将当前位置board[i][j]恢复原来的数值。
代码
class Solution {
public boolean exist(char[][] board, String word) {
for(int i = 0;i<board.length;i++){
for(int j =0;j<board[i].length;j++){
if(fun(board,word,i,j,0))
return true;
}
}
return false;
}
public boolean fun(char[][] board, String word,int i,int j,int index){
if(index >= word.length())
return true;
if(i < 0 || i >= board.length || j < 0 || j >= board[0].length)
return false;
if(board[i][j] == word.charAt(index++)){
char c = board[i][j];
board[i][j] = '#';
boolean res =fun(board,word,i,j+1,index) ||
fun(board,word,i,j-1,index) ||
fun(board,word,i-1,j,index) ||
fun(board,word,i+1,j,index);
board[i][j] = c;
return res;
}
return false;
}
}
LeetCode84
思路
准备单调递增栈存放数组下标,因为这样可以从栈顶找到左边第一个比自己小的下标的下一个,这样从当前下标出发到第一个比自己小的柱子的下标就是矩形面积的宽度,然后在乘当前柱子的高度就是面积,如果当前柱子大于栈顶的下标对应的柱子高度,就入栈,否则不断出栈,计算栈顶的柱子所能形成的矩形面积,然后更新最大矩形面积。
代码
class Solution {
public int largestRectangleArea(int[] heights) {
Stack<Integer> stack = new Stack<>();
int res = 0;
for(int i = 0;i<=heights.length;i++){
int h =0;
if(i == heights.length){
h = 0;
}else{
h = heights[i];
}
while(!stack.isEmpty() && h<heights[stack.peek()]){
int height = heights[stack.pop()];
int start = (stack.isEmpty()) ? -1:stack.peek();
int area = (i-start-1)*height;
res = Math.max(res,area);
}
stack.push(i);
}
return res;
}
}