LeetCode 496. 下一个更大元素 I / 301. 删除无效的括号 / 869. 重新排序得到 2 的幂
Posted Zephyr丶J
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 496. 下一个更大元素 I / 301. 删除无效的括号 / 869. 重新排序得到 2 的幂相关的知识,希望对你有一定的参考价值。
496. 下一个更大元素 I
2021.10.26 每日一题
题目描述
给你两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。
请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。
nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。
示例 1:
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
对于 num1 中的数字 4 ,你无法在第二个数组中找到下一个更大的数字,因此输出 -1 。
对于 num1 中的数字 1 ,第二个数组中数字1右边的下一个较大数字是 3 。
对于 num1 中的数字 2 ,第二个数组中没有下一个更大的数字,因此输出 -1 。
示例 2:
输入: nums1 = [2,4], nums2 = [1,2,3,4].
输出: [3,-1]
解释:
对于 num1 中的数字 2 ,第二个数组中的下一个较大数字是 3 。
对于 num1 中的数字 4 ,第二个数组中没有下一个更大的数字,因此输出 -1 。
提示:
1 <= nums1.length <= nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 10^4
nums1和nums2中所有整数 互不相同
nums1 中的所有整数同样出现在 nums2 中
进阶:你可以设计一个时间复杂度为 O(nums1.length + nums2.length) 的解决方案吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/next-greater-element-i
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
先用单调递减的栈找出每个元素右边第一个比它大的元素,比栈顶元素小,放入,比栈顶元素大,弹出并记录在map中,然后直接查找就可以了
class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
//记得上次是不会做的,尽管是简单题
//思路:要在O1内找到比当前大的
//首先处理nums2,用栈处理,单调栈,找第一个比自己大的,存入map中
int l = nums2.length;
Stack<Integer> stack = new Stack<>();
Map<Integer, Integer> map = new HashMap<>();
stack.push(nums2[0]);
for(int i = 1; i < l; i++){
int temp = nums2[i];
while(!stack.isEmpty() && temp > stack.peek()){
int p = stack.pop();
map.put(p, temp);
}
stack.push(temp);
}
while(!stack.isEmpty()){
map.put(stack.pop(), -1);
}
int[] res = new int[nums1.length];
for(int i = 0; i < nums1.length; i++){
int temp = nums1[i];
res[i] = map.get(temp);
}
return res;
}
}
301. 删除无效的括号
2021.10.27 每日一题
题目描述
给你一个由若干括号和字母组成的字符串 s ,删除最小数量的无效括号,使得输入的字符串有效。
返回所有可能的结果。答案可以按 任意顺序 返回。
示例 1:
输入:s = “()())()”
输出:["(())()","()()()"]
示例 2:
输入:s = “(a)())()”
输出:["(a())()","(a)()()"]
示例 3:
输入:s = “)(”
输出:[""]
提示:
1 <= s.length <= 25
s 由小写英文字母以及括号 ‘(’ 和 ‘)’ 组成
s 中至多含 20 个括号
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-invalid-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
又看范围,又看到不多,然后第一反应肯定又是回溯
先统计要删多少个左括号和右括号,然后回溯删除,用set去重
class Solution {
Set<String> set = new HashSet<>();
public List<String> removeInvalidParentheses(String s) {
//看到数据范围,想到的是状态压缩,但仔细一想好像不行
//然后再想栈,左边遍历一次,右边遍历一次,不行
//先求出最少需要删除几个,然后再删除
int l = s.length();
int left = 0; //要删除的左右括号的数量
int right = 0;
for(int i = 0; i < l; i++){
char c = s.charAt(i);
if(c == '(')
left++;
if(c == ')'){
if(left > 0)
left--; //匹配
else
right++; //无法匹配
}
}
//这是left和right就是要删除的左右括号的数量
//回溯删括号
getRemove(s, left, right, 0, 0, 0);
List<String> res = new ArrayList<>(set);
//if(res.isEmpty()){
// res.add("");
//}
return res;
}
//当前位置,当前删除的左括号数量和右括号数量
public void getRemove(String s, int left, int right, int idx, int lc, int rc){
if(lc == left && rc == right){
boolean flag = isValid(s);
//如果是有效的,那么加到结果集中;否则返回
if(flag)
set.add(s);
return;
}
//如果删多了,那么返回
if(lc > left || rc > right)
return;
//如果剩下的数量不够了
if(s.length() - idx < left - lc + right - rc)
return;
char c = s.charAt(idx);
//如果当前字符不是括号,不管
if(c != '(' && c != ')'){
getRemove(s, left, right, idx + 1, lc, rc);
return;
}
else if(c == '('){
//删除当前字符
String temp = s.substring(0, idx) + s.substring(idx + 1, s.length());
getRemove(temp, left, right, idx, lc + 1, rc);
}else if(c == ')'){
String temp = s.substring(0, idx) + s.substring(idx + 1, s.length());
getRemove(temp, left, right, idx, lc, rc + 1);
}
//回溯
getRemove(s, left, right, idx + 1, lc, rc);
}
public boolean isValid(String s){
int l = s.length();
int left = 0;
for(int i = 0; i < l; i++){
char c = s.charAt(i);
if(c == '(')
left++;
else if(c == ')'){
left--;
if(left < 0)
return false;
}
}
return left == 0;
}
}
没想到这个题也能用广度优先搜索,思路就是将字符串放在栈中,然后每次弹出当前字符串,因为可能重复,所以用set来代替栈更好
然后对当前字符串的每一个括号进行删除,然后放在新的set中,用新的set代替旧的set
每进行新的一轮时,set中的字符串长度都是相同的,所以判断当前set中的字符串有没有符合条件的,如果有符合条件的,那么直接输出就好了,因为长度是最大的
class Solution {
public List<String> removeInvalidParentheses(String s) {
//没想到这个也能广度优先
//就是先删除一个括号,然后再扩展
int l = s.length();
List<String> res = new ArrayList<>();
//用set充当栈的角色
Set<String> set = new HashSet<>();
set.add(s);
while(true){
//遍历所有的当前字符串,都是同一个长度的字符串
for(String temp : set){
if(isValid(temp))
res.add(temp);
}
//如果这个长度是有效的,那么输出,因为就是最短的长度
if(res.size() > 0)
return res;
Set<String> cur = new HashSet<>();
for(String temp : set){
//遍历所有的字符
for(int i = 0; i < temp.length(); i++){
char c = temp.charAt(i);
//如果和上一个字符相同,说明重复了,不需要考虑了
if(i > 0 && c == temp.charAt(i - 1))
continue;
if(temp.charAt(i) == '(' || temp.charAt(i) == ')'){
cur.add(temp.substring(0, i) + temp.substring(i + 1));
}
}
}
set = cur;
}
}
public boolean isValid(String s){
int l = s.length();
int left = 0;
for(int i = 0; i < l; i++){
char c = s.charAt(i);
if(c == '(')
left++;
else if(c == ')'){
left--;
if(left < 0)
return false;
}
}
return left == 0;
}
}
三叶姐将删除变成添加,每次遍历到一个括号,需要看这个括号添加以后,是否依然能够满足条件,如果满足条件了并且长度也等于最后的长度了,那么就可以将这个字符串加到最后的结果集中
这样做可以不用最后一步判断这个字符串是否是合法的这一步操作
class Solution {
Set<String> set = new HashSet<>();
int n, max, len;
String s;
public List<String> removeInvalidParentheses(String _s) {
s = _s;
n = s.length();
int l = 0, r = 0;
for (char c : s.toCharArray()) {
if (c == '(') {
l++;
} else if (c == ')') {
if (l != 0) l--;
else r++;
}
}
len = n - l - r;
int c1 = 0, c2 = 0;
for (char c : s.toCharArray()) {
if (c == '(') c1++;
else if (c == ')') c2++;
}
max = Math.min(c1, c2);
dfs(0, "", l, r, 0);
return new ArrayList<>(set);
}
void dfs(int u, String cur, int l, int r, int score) {
if (l < 0 || r < 0 || score < 0 || score > max) return ;
if (l == 0 && r == 0) {
if (cur.length() == len) set.add(cur);
}
if (u == n) return ;
char c = s.charAt(u);
if (c == '(') {
dfs(u + 1, cur + String.valueOf(c), l, r, score + 1);
dfs(u + 1, cur, l - 1, r, score);
} else if (c == ')') {
dfs(u + 1, cur + String.valueOf(c), l, r, score - 1);
dfs(u + 1, cur, l, r - 1, score);
} else {
dfs(u + 1, cur + String.valueOf(c), l, r, score);
}
}
}
作者:AC_OIer
链接:https://leetcode-cn.com/problems/remove-invalid-parentheses/solution/gong-shui-san-xie-jiang-gua-hao-de-shi-f-asu8/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
869. 重新排序得到 2 的幂
2021.10.28 每日一题
题目描述
给定正整数 N ,我们按任何顺序(包括原始顺序)将数字重新排序,注意其前导数字不能为零。
如果我们可以通过上述方式得到 2 的幂,返回 true;否则,返回 false。
示例 1:
输入:1
输出:true
示例 2:
输入:10
输出:false
示例 3:
输入:16
输出:true
示例 4:
输入:24
输出:false
示例 5:
输入:46
输出:true
提示:
1 <= N <= 10^9
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reordered-power-of-2
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
我的想法就是将所有2的幂都找出来,然后放在map集合中,然后判断所给的数,每个数字的个数是否相同
class Solution {
static int base = 1;
static Map<Integer, int[]> map = new HashMap<>();
static{
while(base <= (int)1e9){
int[] nums = new int[10];
int cur = base;
while(base != 0){
int temp = base % 10;
nums[temp]++;
base /= 10;
}
map.put(cur, nums);
base = cur * 2;
}
}
public boolean reorderedPowerOf2(int n) {
int[] count = new int[10];
while(n != 0){
int temp = n % 10;
count[temp]++;
n /= 10;
}
for(Map.Entry<Integer, int[]> entry : map.entrySet()){
int temp = entry.getKey();
int[] nums = entry.getValue();
for(int i = 0; i < 10; i++)以上是关于LeetCode 496. 下一个更大元素 I / 301. 删除无效的括号 / 869. 重新排序得到 2 的幂的主要内容,如果未能解决你的问题,请参考以下文章
[JavaScript 刷题] 栈 - 下一个更大元素 I, leetcode 496