
解题思路:
- dp 数组的含义: 在数组中是否存在一个子集,其和为 i。
- 递推公式: dp[i] |= dp[i - num]。
- dp 数组初始化: dp[0] = true。
- 遍历顺序: 从大到小去遍历,从 i = target 开始,直到 i = num。确保每个数只用一次。
- 打印 dp 数组
Java代码:
java
class Solution {
public boolean canPartition(int[] nums) {
int sum = 0;
for (int num : nums)
sum += num;
if (sum % 2 != 0)
return false;
int target = sum / 2;
boolean[] dp = new boolean[target + 1];
dp[0] = true;
for (int num : nums) {
for (int i = target; i >= num; i--) {
dp[i] |= dp[i - num];
}
}
return dp[target];
}
}
复杂度分析:
- 时间复杂度: O(n * target)。
- 空间复杂度: O(target)。
解题思路:
可以使用栈来解决这个问题。核心思想是利用栈来跟踪未匹配的括号的索引。初始化时,栈中压入一个基准索引 -1,用于后续计算有效子串的长度。遍历字符串时:
- 遇到左括号 '(',将其索引压入栈中。
- 遇到右括号 ')',弹出栈顶元素。此时:
- 若栈为空,说明当前右括号无匹配,将当前索引压入栈作为新基准。
- 若栈不为空,当前有效子串长度为当前索引与栈顶元素的差值,更新最大值。
此方法确保每次弹出栈顶后,栈顶元素即为最近未匹配的左括号或基准点,从而快速计算有效长度。
Java代码:
java
public class Solution {
public int longestValidParentheses(String s) {
Deque<Integer> stack = new ArrayDeque<>();
stack.push(-1);
int maxLen = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '(') {
stack.push(i);
} else {
stack.pop();
if (stack.isEmpty()) {
stack.push(i);
} else {
maxLen = Math.max(maxLen, i - stack.peek());
}
}
}
return maxLen;
}
}
复杂度分析:
- 时间复杂度: O(n)。
- 空间复杂度: O(n)。