LeetCode 力扣 刷题记录(31 - 35)题目+算法分析+Cpp解答

24 篇文章 0 订阅
17 篇文章 0 订阅
GitHub链接:https://github.com/WilliamWuLH/LeetCode
如果你觉得不错可以 ⭐Star 和 Fork ❤

31.Next Permutation

找规律:

​ 找到下一个按照字典序的排列,所以思路应该是从排列的尾部开始找。

​ 首先从排列的尾部往前找,找到第一个 nums[ i-1 ] < nums[ i ] 的位置,此时说明通过将 nums[ i-1 ] 和排列在 nums[ i-1 ] 后面的并且比 nums[ i-1 ] 大的数 nums[ j ] 互换位置,将得到更大的排列。

​ 如果找不到 nums[ i-1 ] < nums[ i ] 的位置,则说明此时的排列是最大的,直接将整个排列进行反转,得到最小的排列。

​ 若找到 nums[ i-1 ] < nums[ i ] 的位置,此时的任务是找到一个数和 nums[ i-1 ] 进行交换,这个数需要满足:这个数排列在 nums[ i-1 ] 的后面,并且是比 nums[ i-1 ] 大的数中最小的那一个数。

​ 完成交换后,由于 nums[ i-1 ] 已经比之前更大了,所以需要将排在 nums[ i-1 ] 后面的数变为最小的排列,即把在 nums[ i-1 ] 后面的排列进行反转。

​ 完成交换和反转之后便得到了下一个按照字典序的排列。

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int pos = nums.size()-1;
        while(pos > 0 && nums[pos] <= nums[pos-1])
            pos--;        
        reverse(nums.begin()+pos,nums.end());
        if(pos > 0){
            for(int i=pos;i<nums.size();i++){
                if(nums[i] > nums[pos-1]){
                    swap(nums[pos-1],nums[i]);
                    break;
                }
            }
        }
        return;
    }
};

32.Longest Valid Parentheses

动态规划:
class Solution {
public:
    int longestValidParentheses(string s) {
	    int ans = 0;
        int len = s.length();
		vector<int> dp(len, 0);
		for(int i=1; i<len; i++){
            if(s[i] == ')'){
                if(s[i-1] == '('){
                    dp[i] = i-1>0 ? dp[i-2]+2 : 2;
                }
                else if( i-1-dp[i-1] >=0 && s[i-1-dp[i-1]] == '('){
                    if( i-dp[i-1]-2 >= 0){
                       dp[i] = dp[i-1] + 2 + dp[i-dp[i-1]-2];
                    }
                    else{
                        dp[i] = dp[i-1] + 2;
                    }
                }
            }
            ans = max(ans, dp[i]);
        }
        return ans;
    }
};
用stack栈 存 “(” 的位置:

​ 在栈中的栈底元素是此时有效括号字符串的开始位置。

class Solution {
public:
    int longestValidParentheses(string s) {
	    int ans = 0;
        int len = s.length();
		stack<int> front;
        front.push(-1);
		for(int i=0; i<len; i++){
            if(s[i] == '(')
                front.push(i);
            else{
                front.pop();
                if(front.empty())
                    front.push(i);
                else
                    ans = max(ans, i-front.top());
            }
        }
        return ans;
    }
};

33.Search in Rotated Sorted Array

二分查找:

​ 由于该“旋转有序数组”的特性,在对其进行划分时,划分出来的两个部分一定有一部分是完全有序的,另一部分是部分有序的。

​ 根据这个特性,我们可以取出两个部分中完全有序的那一部分进行讨论:

​ 由于数组是完全有序的,所以可以通过判断大小知道目标数字是否在这一部分。

​ 如果目标数字不在完全有序的那一部分,那么一定在另一部分。

​ 通过上述的判断可以进行二分查找,不断缩小查找范围,直到找到目标数字的位置或者没找到目标数字。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0,right = nums.size()-1;
        while(left <= right){
            if(left == right){
                if(nums[left] == target)
                    return left;
                else
                    return -1;
            }
            int mid = (left + right)/2;
            if(nums[mid] == target)
                return mid;
            if(nums[left] <= nums[mid]){
                if(nums[left] <= target && target < nums[mid]){
                    right = mid;
                    continue;
                }
                else{
                    left = mid+1;
                    continue;
                }
            }
            else{
                if(nums[mid] < target && target <= nums[right]){
                    left = mid+1;
                    continue;
                }
                else{
                    right = mid;
                    continue;
                }
            }
        }
        return -1;
    }
};

34.Find First and Last Position of Element in Sorted Array

二分法 + 边界判断 + 取值判断:

​ 二分法的重点和难点主要为:

  • 左右边界的取值,主要是右边界( size 还是 size - 1 )。
  • while 循环的判断条件( < 还是 <= ),这和左右边界的取值有关。
  • 中间位置的计算,使用 left + (right - left)/2 可以避免溢出。
  • 不要用 else,全部都用 else if 把情况说明清楚。
  • 针对不同情况,左右边界应该如何收缩:这和一开始左右边界的取值有关
  • 最后取值(取出位置或者是坐标)时,需要判断该位置是否有效(即该位置在合法范围内),并且需要判断该位置的值是否为目标数值。
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int left = 0,right = nums.size();
        vector<int> ans = {-1,-1};
        while(left < right){
            int mid = left + (right - left)/2;
            if(nums[mid] == target)
                right = mid;
            else if(nums[mid] < target)
                left = mid+1;
            else if(nums[mid] > target)
                right = mid;
        }
        if(left < nums.size() && nums[left] == target)
            ans[0] = left;
        left = 0,right = nums.size();
        while(left < right){
            int mid = left + (right - left)/2;
            if(nums[mid] == target)
                left = mid+1;
            else if(nums[mid] < target)
                left = mid+1;
            else if(nums[mid] > target)
                right = mid;
        }
        if(right-1 < nums.size() && nums[right-1] == target)
            ans[1] = right-1;
        return ans;
    }
};

35.Search Insert Position

二分查找:
class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int left = 0,right = nums.size()-1;
        while(left <= right){
            int mid = left + (right - left)/2;
            if(nums[mid] == target)
                return mid;
            else if(nums[mid] < target)
                left = mid+1;
            else if(nums[mid] > target)
                right = mid-1;
        }
        return left;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值