数组
- Leetcode 119: Pascal’s Triangle II
easy
- 解题关键:
- 暴力解法,构造pascal’s triangle, 找到对应rowIndex的行,构造成List
// 构造pascal's triangle的逻辑, 注意数组长度是rowIndex + 1 int[][] triangle = new int[rowIndex + 1][rowIndex + 1] for (int i = 0; i < rowIndex + 1; i ++) { for (int j = 0; j <= i; j ++) { if (j == 0 || j == i) { triangle[i][j] = 1; } else { // 根据pascal's triangle定义 triangle[i][j] = triangle[i - 1][j - 1] + triangle[i][j - 1]; } } }
- 暴力解法,构造pascal’s triangle, 找到对应rowIndex的行,构造成List
- 解题关键:
- Leetcode 915: Partition Array into Disjoint Intervals
medium
- 解题关键:
- 此题最关键的是找到left side的最大值,确保right side中任意一个值都大于该值
- 同时要找到right side中在数组里index最小的位置
- 使用 [[贪心算法(Greedy Algorithm)]]
// 初始化两个最大值,一个是当前left side最大值,一个是用于遍历整个数组的可能出现的下一个最大值 // 初始化为当前数组第一个值 int currentMax = nums[0]; int nextMax = nums[0]; int ret = 0; // 遍历数组 for (int i = 1; i < nums.length; i ++) { int currentVal = nums[i]; // 若当前值大于nextMax,则更新nextMax nextMax = Math.max(currentVal, nextMax); // 若当前值小于当前最大值currentMax,记录下当前索引,并更新左边当前最大值为nextMax if (currentVal < currentMax) { currentMax = nextMax; ret = i; } } // 当前坐标为left side最后一个索引,因此应返回ret + 1 return ret + 1
- 解题关键:
字符串
-
Leetcode 20: Valid Parentheses
easy
- 解题关键:
- 1,corner case判断,若字符串为空,则直接返回true
if (s.length() == 0) return true;
- 2,根据题意,相邻的() [] {}即为valid,可以考虑使用栈结构,后进先出(Last In First Out)原则,匹配到成pair的符号则pop元素,最后合法的字符,栈一定会被清空
for (char c: s.toCharArray()) { // 如果是open状态的符号,则push进栈 if (c == '(' || c == '[' || c == '{') { stack.push(c); } else { // 若栈此时为空,但还未遍历完,说明下一个char有可能是'}])'中的一个,说明是不合法的,返回false if (stack.isEmpty()) { return false; } // 若下一个元素是'}])'中的一个,与当前栈的元素进行比对 if (c == ']' && stack.peek() != '[') { return false; } else if (c == '}' && stack.peek() != '{') { return false; } else if (c == ')' && stack.peek() != '(') { return false; } // 若未返回false,说明匹配pair成功,从栈里pop该元素 stack.pop(); } } return stack.isEmpty();
- 1,corner case判断,若字符串为空,则直接返回true
- 解题关键:
-
Leetcode 22: Generate Parentheses
medium
- 解题关键:理解[[回溯算法(backtracking)]]
-
- 解题关键:
- 理解题意,是将两个字符串的二进制数转化成十进制,相加后再转化为二进制数
- 需要注意当a, b的二进制非常长的时候,会超出默认类型的长度(int, Integer),因此考虑使用
BigInteger
类型,或者手写二进制转十进制
StringBuilder ret = new StringBuilder(); // index starts from the end int aIndex = a.length() - 1; int bIndex = b.length() - 1; int carry = 0; while (aIndex >= 0 || bIndex >= 0) { int sum = 0; if (aIndex >= 0) { // change char to int sum += a.charAt(aIndex) - '0'; aIndex --; } // the same to string b if (bIndex >= 0) { sum += b.charAt(bIndex) - '0'; bIndex --; } sum += carry; ret.append(sum % 2); carry = sum / 2; } if (carry > 0) { ret.append(carry); } return ret.reverse().toString();
- 解题关键:
-
Leetcode 443: String Compression
medium
- 解题关键
- 本题使用滑动窗口算法解决
-
1,corner case判断,若长度为1,直接返回,因为长度为1的字符后面数字不用添加
int length = chars.length; if (length == 1) { return length; }
-
2,定义窗口的左右边界
int left = 0; int right = 0; // i为遍历索引,便于in-place change,结合题意需要constant extra space int i = 0;
-
3,核心逻辑
// 以窗口右边界为基准 while (right < length) { // 定义一个计数器,保存每个字符的数量 int count = 0; // 存储每个窗口的字符 char c = chars[left]; while (right < length && chars[right] == c) { // 基于窗口右边界进行遍历,计算窗口范围 count ++; right ++; } // in-place change chars[i] = c; // i索引加1,即字符的后一位为计数值 i ++; // 若count大于1,则需要在字符后添加数字 if (count > 1) { // 若计数大于两位数,用for循环将数字转为char array,然后依次更换chars中的位置,同时i递增 for (char character: Integer.toString(count).toCharArray()) { chars[i] = character; i ++; } } // 当right遍历到下一个字符时,此时将窗口左边界更新,重新开启一个新窗口计算下一组字符 left = right; } // 返回最后的i return i;
-
- 本题使用滑动窗口算法解决
- 解题关键
-
Leetcode 791: Custom Sort String
medium
- 解题思路
-
根据题意,因为待排序的的字符长度最大为200,而元素范围是26个英文字母,基于该特性可以使用计数排序算法
// 创建一个长度为26的数组存储排序字符计数 int[] tmp = new int[26]; for (char c: str.toCharArray()) { // 根据char - 'a'获得在tmp数组中的索引位置,同时计数 tmp[c - 'a'] ++; } // 例如str为"abcddd",那么tmp此时为 // [1, 1, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
-
由于排序规则是根据给定的字符来指定,因此基于排序规则的字符在tmp数组中找到对应位置,并计算该字符数量进行递减
for (char c: order.toCharArray()) { while (tmp[c - 'a'] > 0) { sb.append(c); } }
-
其余字符根据字母顺序排序插入StringBuilder即可
for (int i = 0; i < 26; i ++) { while (tmp[i] -- > 0) { sb.append((char) (i + 'a')); } }
-
- 解题思路