“Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。”
31. 下一个排列
一、题目描述:
整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。
例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。
例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。 类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。 而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。 给你一个整数数组 nums ,找出 nums 的下一个排列。
必须 原地 修改,只允许使用额外常数空间。
示例 1:
输入: nums = [1,2,3]
输出: [1,3,2]
二、思路分析:
倒序查找相邻的数字中, 右边大于左边的数对 (i,j), 使用 k 记录 i, 从 i 的右边找到最小比nums[k]大的数字, 与 nums[k] 交换, 然后对 k+ 1 到 n - 1 之间的数字进行交换即可
三、AC 代码:
public void nextPermutation(int[] nums) {
int k = -1;
int n = nums.length;
for (int i = n - 1; i > 0; i--) {
if (nums[i] > nums[i - 1]) {
k = i - 1;
break;
}
}
if (k != -1) {
for (int i = n - 1; i > 0; i--) {
if (nums[i] > nums[k]) {
int t = nums[i];
nums[i] = nums[k];
nums[k] = t;
break;
}
}
}
int l = k + 1;
int r = n - 1;
while (l < r) {
int t = nums[l];
nums[l] = nums[r];
nums[r] = t;
l++;
r--;
}
}
32. 最长有效括号
一、题目描述:
给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
示例 1:
输入:s = "(()"
输出:2
二、思路分析:
- 动态规划
状态转移: dp[i] 为, 以 i 结尾的字符串中最长有效括号子串的长度
char[i] == '(' 时 dp[i] = 0
char[i] == ')' 时, left = i - 1 - dp[i - 1], 考虑 left 位置的字符, char[left] == '('时
dp[i] = dp[i - 1] + 2 + dp[left - 1]
tip : 注意 Index 的合法性, 不要越界
三、AC 代码:
class Solution {
public int longestValidParentheses(String s) {
if (s == null || s.length() == 0) return 0;
char[] chars = s.toCharArray();
int[] dp = new int[s.length()];
int ans = 0;
for (int i = 0; i < s.length(); i++) {
char c = chars[i];
if (c == ')' && i > 0) {
int l = i - 1 - dp[i - 1];
if (l >= 0 && chars[l] == '(') {
dp[i] = dp[i - 1] + 2;
if (l - 1 >= 0) {
dp[i] += dp[l - 1];
}
}
}
ans = Math.max(ans, dp[i]);
}
return ans;
}
}