日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

leetcode-300 最长上升子序列

發布時間:2023/11/27 生活经验 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 leetcode-300 最长上升子序列 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目描述:
給定一個無序的整數數組,找到其中最長上升子序列的長度。

示例:

輸入: [10,9,2,5,3,7,101,18]
輸出: 4
解釋: 最長的上升子序列是 [2,3,7,101],它的長度是 4。

說明:
可能會有多種最長上升子序列的組合,你只需要輸出對應的長度即可。
你算法的時間復雜度應該為 O(n^2) 。

方法一(暴力法):
即針對數組的每一個元素都有兩種選擇,取或者不取(取的前提是當前元素大于上一個元素,則上升子序列++),最終遞歸到最后的一個元素,將結果返回。

實現如下:

int lengthOfLIS(vector<int>& nums) {return get_lengthOfLIS(nums, -1, 0);
}
int get_lengthOfLIS(vector<int> &num, int prev, int curr) {if(curr == num.size()) {return 0;}int taken = 0;if(num[curr] > prev) {taken = get_lengthOfLIS(num, num[curr], curr+1);}int notaken = get_lengthOfLIS(num, prev, curr+1);return max(taken, notaken);
}

但是因為暴力解法的時間復雜度較高,針對每個元素都有兩種選擇,時間復雜度為O(2^n)

方法二(DP動態規劃):

  1. 狀態的定義
    dp[i] 代表以當前元素 nums[i]結尾(最長上升子序列包括nums[i])的最長上升子序列的大小
  2. 狀態轉移方程
    dp[i] = (nums[i] > nums[j]) ? max{dp[0]…dp[j]} + 1 ,1; (j>=0 && j < i)
    以上方程的意思是,找到所有nums[i]左側比nums[i]小的元素的個數,在其基礎上+1

實現如下:

int lengthOfLIS(vector<int>& nums) {if(nums.size() <= 1) return nums.size();vector<int> dp(nums.size(),0);int res = 1,i = 1, j = 0;dp[0] = 1;for(i = 1;i < nums.size(); ++i) {dp[i] = 1;for (j = 0;j < i; ++j) {if(nums[i] > nums[j] && dp[i] < dp[j] + 1) { //找到nums[i]左邊比nums[i]小的元素,取它的dp[j] + 1給到dp[i]dp[i] = dp[j]+1;}}if(res < dp[i]) { //res取最大即可res = dp[i];}}return res;
}

以上方法的時間復雜度為O(n^2),j的遍歷的層數和i的個數基本一致

方法三(遞增棧 + 二分):
維護一個持續遞增的棧,元素添加進來有兩種規則:

  1. 當要添加的元素大于棧頂元素,則壓棧
  2. 當要添加的元素小于棧頂元素,那么在棧中找到該元素的插入位置,將其替換該位置的元素

只有當滿足第一中情況的時候棧的大小才會增加,否則棧的大小是固定的,優化的辦法是使用二分法查找待插入的位置

實現如下:

int lengthOfLIS(vector<int>& nums) {if (nums.size() == 0) return 0;vector<int> stack;//使用vector代替棧stack.push_back(nums[0]);for (int i = 1;i < nums.size(); ++i) {if (nums[i] > stack.back()) {stack.push_back(nums[i]);} else {int pos = binary_search(stack,nums[i]);stack[pos] = nums[i];}}return stack.size();
}//二分查找,返回待插入元素的下標
int binary_search(vector<int> &stack,int target) {int index = -1;int begin = 0;int end = stack.size() - 1;while (index == -1) {int mid = (begin + end) / 2;if (target == stack[mid]) {index = mid;} else if (target < stack[mid]) {if (mid == 0 || target > stack[mid - 1]) {index = mid;}end = mid - 1;} else {if (mid == stack.size() - 1 || target < stack[mid + 1] ) {index = mid + 1;}begin = mid + 1;}}return index;
}

時間復雜度為O(N*logn),遍歷n次,每次二分查找的時間復雜度是logn

總結

以上是生活随笔為你收集整理的leetcode-300 最长上升子序列的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。