Day08 括号匹配、最长递增子序列二维拓展(信封嵌套)
最长有效括号
- 思路:
- 难点在 括号匹配且连续
动态规划个人思路
- dp[i] 表示以第i个位置为有效括号的最大连续长度
- 确定括号是否有效
- 遍历 ( 并入栈。入 当前下标
- 遍历 ) ,如果此时栈中没有与之匹配的,则dp[i]直接为 0
- 如果有与之匹配的,
class Solution { public int longestValidParentheses(String s) { char[] array = s.toCharArray(); Stack<Integer> stack = new Stack<>(); int ans = 0; int[] dp = new int[array.length]; for (int i = 0; i < array.length; i++) { char item = array[i]; if (item == '(') { stack.push(i); } else { if (stack.isEmpty()) { dp[i] = 0; } else { Integer index = stack.pop(); int pre = 0, next = 0; if (index - 1 >= 0) { pre = dp[index - 1]; } if (index + 1 < array.length) { next = dp[i - 1]; } dp[index] = 2 + pre + next; dp[i] = dp[index]; ans = Math.max(dp[i], ans); } } } return ans; } } - 标准动态规划思路
- dp[i]表示以i为结尾的有效连续括号长度
- 当i为 ) 并且对应 i - 1 为 (,则
- 。上一个结果 +2
- 注意判断 i - 2的边界
- 。上一个结果 +2
- 当i为 ) 并且对应 i - 1 为 ),需要考虑前面是否有与之对应匹配的 (
- 如果有,则它的下标一定为 。前一个有效括号的 ( 的上一个
- 注意判断 的边界
- 如果确实满足,还需要 和之前的dp数组是否能连接上
-
- 注意判断 的边界
- 如果有,则它的下标一定为 。前一个有效括号的 ( 的上一个
class Solution { public int longestValidParentheses(String s) { int ans = 0; int[] dp = new int[s.length()]; for (int i = 1; i < s.length(); i++) { char item = s.charAt(i); if (item == ')') { if (s.charAt(i - 1) == '(') { dp[i] = (i - 2 >= 0 ? dp[i - 2] : 0) + 2; } else if (i - dp[i - 1] - 1 >= 0 && s.charAt(i - dp[i - 1] - 1) == '(') { // )对应的有效括号跟他对象的(之前的 dp时候能连接在一起 dp[i] = dp[i - 1] + ((i - dp[i - 1] - 2) >= 0 ? dp[i - dp[i - 1] - 2] : 0) + 2; } ans = Math.max(ans, dp[i]); } } return ans; } } - 栈
- 当前元素为 ( 时,下标入栈。栈始终维护最后一个匹配的 ) 的下标
- 当前元素为 ) 时,先从栈中出栈
- 当栈为空,将当前下标i入栈。维护最后一个匹配的 )
- 栈不为空,
class Solution { public int longestValidParentheses(String s) { int ans = 0; //stack存储上一个没有被匹配的)的下标 Stack<Integer> stack = new Stack<>(); stack.push(-1); for (int i = 0; i < s.length(); i++) { char item = s.charAt(i); if (item == '(') { stack.push(i); } else { stack.pop(); if (stack.isEmpty()) { stack.push(i); } else { ans = Math.max(ans, i - stack.peek()); } } } return ans; } }
2、俄罗斯套娃信封问题
- 思路:
- 控制二维中的一维有序,然后在另一维上进行递增子序列求解
class Solution { public int maxEnvelopes(int[][] envelopes) { //按照宽度进行升序排序,当宽度一样时 //,按照高度进行倒序排序(保证,相同宽度但高度大的不被计算在结果内) PriorityQueue<int[]> queue = new PriorityQueue<>((a,b)->{ if (a[0] == b[0]){ return b[1] - a[1]; }else { return a[0] - b[0]; } }); for (int[] item : envelopes) { queue.offer(item); } int[] arr = new int[envelopes.length]; for (int i = 0; i < arr.length; i++) { arr[i] = queue.poll()[1]; } return lengthOfLIS(arr); } private int lengthOfLIS(int[] arr){ int[] tail = new int[arr.length]; tail[0] = arr[0]; int last = 0; for (int i = 1; i < arr.length; i++) { int item = arr[i]; if (item > tail[last]){ tail[++last] = item; }else { int l = 0, r = last; while (l <= r){ int mid = l + (r - l) / 2; if (tail[mid] >= item){ r = mid - 1; }else { l = mid + 1; } } tail[l] = item; } } return last + 1; } }