前言
本文隶属于专栏《LeetCode 刷题汇总》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!
本专栏目录结构请见LeetCode 刷题汇总
正文
幕布
31. 下一个排列
题解
后->前,找第一个连续降序前一个数字,然后二分查找刚好比它大的,交换,降序改升序
class Solution {
public void nextPermutation(int[] nums) {
int n = 0;
if(nums == null || (n = nums.length) == 0) return;
// 从后往前查找第一次出现 nums[i] < nums[i+1] 的位置
int i = n-2;
for(; i>=0 && nums[i] >= nums[i+1]; i--) ;
// if i == -1 nums 则整体逆序
if(i >= 0){
// 此时 nums[i+1, n-1] 降序, 查找其中 大于nums[i] 的最大下标,可以直接 从后往前 逆向找
// 因为有序 可以练习一下二分查找
int j = binarySearch(nums, i+1, n-1, nums[i]);
// 交换 i j
swap(nums, i, j);
}
// 此时 nums[i+1, n-1] 仍然降序,将其改为升序,只需要反转即可。
reverse(nums, i+1, n-1);
}
// nums[left, right] 逆序,查找其中 > target 的 最大下标
private int binarySearch(int[] nums, int left, int right, int target){
while(left <= right){
int mid = (left + right) >>> 1;
if(nums[mid] > target){
left = mid + 1; // 尝试再缩小区间
}else{
right = mid - 1;
}
}
return right;
}
private void swap(int[] nums, int i, int j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
private void reverse(int[] nums, int i, int j){
while(i < j){
swap(nums, i++, j--);
}
}
}
32. 最长有效括号
题解
官方题解
动态规划,字符串中对应的索引为有效子串结尾的最长有效括号子串的长度
object Solution {
def longestValidParentheses(s: String): Int = {
if (s.isEmpty) return 0
val n = s.length
//dp 表示 s 中对应的索引为有效子串结尾的最长有效括号子串的长度
val dp = new Array[Int](n)
for (i <- 1 until n) {
if (s(i) == '(') dp(i) = 0
else {
if (s(i - 1) == '(') dp(i) = if (i > 2) dp(i - 2) + 2 else 2
else if (i - dp(i - 1) - 1 >= 0 && s(i - dp(i - 1) - 1) == '(') dp(i) = dp(i - 1) + 2 + (if (i - dp(i - 1) - 2 >= 0) dp(i - dp(i - 1) - 2) else 0)
else dp(i) = 0
}
}
dp.max
}
}
33. 搜索旋转排序数组
题解
官方题解
二分查找,先判断在中间
class Solution {
public int search(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return -1;
}
int start = 0, end = nums.length - 1, mid;
while (start < end) {
mid = start + ((end - start) >> 1);
if (target == nums[mid]) {
return mid;
}
if (nums[start] <= nums[mid]) {
if (target >= nums[start] && target < nums[mid]) {
end = mid - 1;
} else {
start = mid + 1;
}
} else {
if (target > nums[mid] && target <= nums[end]) {
start = mid + 1;
} else {
end = mid - 1;
}
}
}
return nums[start] == target ? start : -1;
}
}
34. 在排序数组中查找元素的第一个和最后一个位置
题解
二分查找,helper(nums, target + 1) - 1
class Solution {
public int[] searchRange(int[] nums, int target) {
int first = helper(nums, target);
if(first == nums.length || nums[first] != target) return new int[]{-1, -1};
return new int[]{first, helper(nums, target + 1) - 1};
}
private int helper(int[] nums, int target){
int low = 0, high = nums.length;
while(low < high){
int mid = low + ((high - low) >> 1);
if(nums[mid] < target) low = mid + 1;
else high = mid;
}
return high;
}
}
35. 搜索插入位置
题解
标准二分
object Solution {
def searchInsert(nums: Array[Int], target: Int): Int = {
val n = nums.length
var low, mid = 0
var high = n - 1
while (low <= high) {
mid = low + ((high - low) >> 1)
if (nums(mid) == target) return mid
else if (nums(mid) > target) high = mid - 1
else low = mid + 1
}
low
}
}