代码随想录算法训练营第11天 | ● 20. 有效的括号 ● 1047. 删除字符串中的所有相邻重复项 ● 150. 逆波兰表达式求值
Posted 小懒懒
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代码随想录算法训练营第11天 | ● 20. 有效的括号 ● 1047. 删除字符串中的所有相邻重复项 ● 150. 逆波兰表达式求值相关的知识,希望对你有一定的参考价值。
第五章 栈与队列part02
今日内容:
● 20. 有效的括号
● 1047. 删除字符串中的所有相邻重复项
● 150. 逆波兰表达式求值
详细布置
20. 有效的括号
讲完了栈实现队列,队列实现栈,接下来就是栈的经典应用了。
大家先自己思考一下 有哪些不匹配的场景,在看视频 我讲的都有哪些场景,落实到代码其实就容易很多了。
题目链接/文章讲解/视频讲解:https://programmercarl.com/0020.%E6%9C%89%E6%95%88%E7%9A%84%E6%8B%AC%E5%8F%B7.html
1047. 删除字符串中的所有相邻重复项
栈的经典应用。
要知道栈为什么适合做这种类似于爱消除的操作,因为栈帮助我们记录了 遍历数组当前元素时候,前一个元素是什么。
150. 逆波兰表达式求值
本题不难,但第一次做的话,会很难想到,所以先看视频,了解思路再去做题
题目链接/文章讲解/视频讲解:https://programmercarl.com/0150.%E9%80%86%E6%B3%A2%E5%85%B0%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%B1%82%E5%80%BC.html
往日任务
● day 1 任务以及具体安排:训练营一期day 1
● day 2 任务以及具体安排:day 2 第一章数组
● day 3 任务以及具体安排:day 3 第二章 链表
● day 4 任务以及具体安排:day 4 第二章 链表
● day 5 周日休息
● day 6 任务以及具体安排:day 6 第三章 哈希表
● day 7 任务以及具体安排:day 7 第三章 哈希表
● day 8 任务以及具体安排:day 8 第四章 字符串
● day 9 任务以及具体安排:day 9 第四章 字符串
● day 10 任务以及具体安排:day 10 第四章 字符串
代码随想录算法训练营第六天 | 242.有效的字母异位词349. 两个数组的交集202. 快乐数1. 两数之和
有效的字母异位词
class Solution
public boolean isAnagram(String s, String t)
/*
* 思路:
* 用数组当做统计26个字母出现次数的哈希表
*
* 参考:
* https://programmercarl.com/0242.%E6%9C%89%E6%95%88%E7%9A%84%E5%AD%97%E6%AF%8D
* %E5%BC%82%E4%BD%8D%E8%AF%8D.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%
* 88%E6%9C%AC
*
*
* 定义一个数组叫做record.用来上记录字符串s里字符出现的次数。
* 需要把字符映射到数组也就是哈希表的索引下标上,因为字符a到字符z的ASCII是26个连续的数值,所以字符a映射为下标0,相应的字符z映射为下标25。
* 再遍历字符串s的时候,只需要将s[i]-'a'所在的元素做+1操作即可,并不需要记住字符a的ASCII,只要求出一个相对数值就可以了。
* 这样就将字符串s中字符出现的次数,统计出来了。
* 那看一下如何检查字符串t中是否出现了这些字符,同样在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再做-1的操作。
* 那么最后检查一下,record数组如果有的元素不为零0,说明字符串s和t一定是谁多了字符或者谁少了字符,return false。
* 最后如果record数组所有元素都为零0,说明字符串s和t是字母异位词,return true。
* 时间复杂度为O(n),空间上因为定义的是一个常量大小的辅助数组,所以空间复杂度为O(1)。
*
*/
int record[] = new int[26]; // 数组哈希表,记录每个字母的出现次数
// 记录字符串s中每个字母出现的次数
for (int i = 0; i < s.length(); i++)
int index = s.charAt(i) - 'a'; // 表示26个字母中的第几个字母
record[index]++;
// 如果字符串t含有某个字母,那么减一
for (int i = 0; i < t.length(); i++)
int index = t.charAt(i) - 'a';
record[index]--;
// record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
for (int i : record)
if (i != 0)
return false;
// record数组所有元素都为零0,说明字符串s和t是字母异位词
return true;
两个数组的交集
class Solution
public int[] intersection(int[] nums1, int[] nums2)
/*
* 思路:
* 使用哈希集合hashSet
*
* 参考:
* https://programmercarl.com/0349.%E4%B8%A4%E4%B8%AA%E6%95%B0%E7%BB%84%E7%9A%84
* %E4%BA%A4%E9%9B%86.html#_349-%E4%B8%A4%E4%B8%AA%E6%95%B0%E7%BB%84%E7%9A%84%E4
* %BA%A4%E9%9B%86
*
* 注意题目特意说明:输出结果中的每个元素一定是唯一的,
* 也就是说输出的结果的去重的,同时可以不考虑输出结果的顺序。
*
* 如果用数组做哈希表,那么假设交集的数字只有5000,那么数组的下标得到4999,
* 造成存储空间的极大浪费。也即,如果哈希值比较少、特别分散、跨度非常大,
* 使用数组就造成空间的极大浪费。所以这个时候可以用哈希集合。
*
* 本题将一个数组变成哈希集合,然后遍历另一个数组与此哈希集合比较,
* 看是否出现过相同的元素。
*
*
*/
// 排除异常条件:数组不存在,或数组长度为0
if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0)
return new int[0];
Set<Integer> set1 = new HashSet<>(); // nums1数组的集合
Set<Integer> interSet = new HashSet<>(); // 交集
// 获得nums1数组的不重复元素
for (int i : nums1)
set1.add(i);
// 从nums2中找到与nums1数组相同的元素
for (int i : nums2)
if (set1.contains(i))
interSet.add(i);
// 集合变为int数组
// 注意hashset先变为stream,才能变为数组
return interSet.stream().mapToInt(x -> x).toArray();
快乐数
class Solution
public boolean isHappy(int n)
/*
* 思路:哈希集合
* 每次按快乐数公式计算的结果,一旦发现新的就存到哈希集合中,
* 如果发现哈希集合中已经存在此数,那么停止计算。(因为遇到
* 重复出现的数后,继续计算又会陷入循环当中)。
*
* 最后检查这个重复的数是否为1。
*
* 参考:
* https://programmercarl.com/0202.%E5%BF%AB%E4%B9%90%E6%95%B0.html
*
*/
Set<Integer> set = new HashSet<>();
// 一直计算快乐数,直到遇到重复的为止
// n!=1是因为题意说直到变成1,变成1就说明是快乐数满足条件可以退出循环了(1没必要再进入循环了)。
while (n != 1 && !set.contains(n))
set.add(n);
n = getNextNumber(n); // 按快乐数公式计算下一个
// 检查重复的数是否为1
return n == 1;
public int getNextNumber(int n)
/*
* 计算快乐数
*/
// 注意怎么取各个位的数字
int result = 0;
while (n != 0)
int tmp = n % 10; // 获得末位数
result += tmp * tmp;
n /= 10; // n的位数-1
return result;
两数之和
class Solution
public int[] twoSum(int[] nums, int target)
/*
* 思路:哈希表 key:数据元素,value:数组元素对应的下表
*
* 什么时候使用哈希法,当我们需要查询一个元素是否出现过,
* 或者一个元素是否在集合里的时候,就要第一时间想到哈希法。
*
* 我们不仅要知道元素有没有遍历过,还有知道这个元素对应的下标,
* 需要使用 key value结构来存放,key来存元素,value来存下标,
* 那么使用map正合适。
*
* 再来看一下使用数组和set来做哈希法的局限:
* 1、数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
* 2、set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,
* 不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x和y的下标。所以set也不能用。
* 此时就要选择另一种数据结构:map。
*
* 参考:
* https://programmercarl.com/0001.%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C.html#%E6
* %80%9D%E8%B7%AF
*
*/
// 存储满足题目条件的两个数的下标
int result[] = new int[2];
// 排除异常:如果数组为null或者数组长度为0
if (nums == null || nums.length == 0)
return result;
// map目的用来存放我们访问过的元素,因为遍历数组的时候,
// 需要记录我们之前遍历过哪些元素和对应的下标,
// 这样才能找到与当前元素相匹配的(也就是相加等于target)
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++)
// 检查两数之和的另一个数是否存在哈希表中
int tmp = target - nums[i];
if (map.containsKey(tmp))
result[1] = i;
result[0] = map.get(tmp); // 获得下标
break;
// map存元素和对应的下标
map.put(nums[i], i);
return result;
以上是关于代码随想录算法训练营第11天 | ● 20. 有效的括号 ● 1047. 删除字符串中的所有相邻重复项 ● 150. 逆波兰表达式求值的主要内容,如果未能解决你的问题,请参考以下文章
代码随想录算法训练营第14天 | ● 理论基础 ● 递归遍历 ● 迭代遍历 ● 统一迭代
代码随想录算法训练营第10天 | ● 理论基础 ● 232.用栈实现队列 ● 225. 用队列实现栈
代码随想录算法训练营第13天 | ● 239. 滑动窗口最大值 ● 347.前 K 个高频元素 ● 总结
代码随想录算法训练营第15天 | ● 层序遍历 10 ● 226.翻转二叉树 ● 101.对称二叉树 2