<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ?LeetCode刷題實(shí)戰(zhàn)300:最長(zhǎng)遞增子序列

          共 8529字,需瀏覽 18分鐘

           ·

          2021-06-23 20:53

          算法的重要性,我就不多說了吧,想去大廠,就必須要經(jīng)過基礎(chǔ)知識(shí)和業(yè)務(wù)邏輯面試+算法面試。所以,為了提高大家的算法能力,這個(gè)公眾號(hào)后續(xù)每天帶大家做一道算法題,題目就從LeetCode上面選 !

          今天和大家聊的問題叫做 最長(zhǎng)遞增子序列,我們先來(lái)看題面:
          https://leetcode-cn.com/problems/longest-increasing-subsequence/


          Given an integer array nums, return the length of the longest strictly increasing subsequence.

          A subsequence is a sequence that can be derived from an array by deleting some or no elements without changing the order of the remaining elements. For example, [3,6,2,7] is a subsequence of the array [0,3,1,6,2,2,7].

          給你一個(gè)整數(shù)數(shù)組 nums ,找到其中最長(zhǎng)嚴(yán)格遞增子序列的長(zhǎng)度。
          子序列是由數(shù)組派生而來(lái)的序列,刪除(或不刪除)數(shù)組中的元素而不改變其余元素的順序。例如,[3,6,2,7] 是數(shù)組 [0,3,1,6,2,2,7] 的子序列。


          示例

          示例 1:

          輸入:nums = [10,9,2,5,3,7,101,18]
          輸出:4
          解釋:最長(zhǎng)遞增子序列是 [2,3,7,101],因此長(zhǎng)度為 4 。

          示例 2:

          輸入:nums = [0,1,0,3,2,3]
          輸出:4

          示例 3:

          輸入:nums = [7,7,7,7,7,7,7]
          輸出:1


          解題

          https://blog.csdn.net/nie2314550441/article/details/107269090


          3.1 方法一:動(dòng)態(tài)規(guī)劃
          動(dòng)態(tài)規(guī)劃遞推公式:dp[i]=max(dp[j])+1,其中0≤j<i且num[j]<num[i]。

          復(fù)雜度分析:
          時(shí)間復(fù)雜度:O(n^2)
          空間復(fù)雜度:O(n)
          以輸入序列 [10,9,2,5,3,7,101,18]為例,數(shù)組變化如下圖所示


          3.2 方法二:貪心 + 二分查找

          貪心法 + 二分法:使用數(shù)組來(lái)進(jìn)行上升序列的積累。如果上升則積累(append),如果下降,則通過二分法找到探索元素的位置進(jìn)行替換(不改變數(shù)組的長(zhǎng)度)。最終返回?cái)?shù)組的長(zhǎng)度。

          設(shè)當(dāng)前已求出的最長(zhǎng)上升子序列的長(zhǎng)度為 len(初始時(shí)為 1),從前往后遍歷數(shù)組 nums,在遍歷到 nums[i] 時(shí):

          如果 nums[i]>dp[len] ,則直接加入到 dp 數(shù)組末尾,并更新 len=len+1;
          否則,在 d 數(shù)組中二分查找,在 dp 數(shù)組中找到第一個(gè)大于或等于 nums[i] 的數(shù) dp[k] ,并更新 d[k]=nums[i]。
          復(fù)雜度分析:

          時(shí)間復(fù)雜度:O(nlogn)
          空間復(fù)雜度:O(n)
          以輸入序列 [10,9,2,5,3,7,101,18]為例,數(shù)組變化如下圖所示:


          最終得到最大遞增子序列長(zhǎng)度為 4。

          #pragma once
          #include <iostream>
          #include <vector>
          #include <algorithm>
          using namespace std;
           
          #define NAMESPACE_LENGTHOFLIS namespace NAME_LENGTHOFLIS {
          #define NAMESPACE_LENGTHOFLISEND }
          NAMESPACE_LENGTHOFLIS
           
          // 動(dòng)態(tài)規(guī)劃
          // 遞推公式:dp[i]=max(dp[j])+1,其中0≤j<i且num[j]<num[i]
          // 時(shí)間復(fù)雜度:O(n^2), 空間復(fù)雜度:O(n)
          class Solution1 
          {

          public:
              int lengthOfLIS(vector<int>& nums) 
              
          {
                  int n=(int)nums.size();
                  if (n == 0) return 0;
                  vector<int> dp(n, 0);
                  int maxLen = 1;
                  for (int i = 0; i < n; ++i)
                  {
                      dp[i] = 1;
                      for (int j = 0; j < i; ++j)
                      {
                          if (nums[j] < nums[i])
                          {
                              dp[i] = max(dp[i], dp[j] + 1);
                              maxLen = max(maxLen, dp[i]);
                          }
                      }
                  }
                  
                  //return *max_element(dp.begin(), dp.end());
                  return maxLen;
              }
          };
           
          // 動(dòng)態(tài)規(guī)劃
          // dp[i] = max(dp[j]) + 1, 其中 0 ≤ j < i 且 num[j] < num[i]
          class Solution
          {

          public:
            // 返回不小于目標(biāo)值的位置
              int search(vector<int> & nums, int target)
              
          {
                  int l = 0;
                  int r = nums.size() - 1;
                  while(l < r)
                  {
                      int mid = (r + l) / 2;
                      if(target == nums[mid])
                         return mid;
                      else if(target > nums[mid])
                         l = mid + 1;
                      else if(target < nums[mid])
                         r = mid;
                  }
                  return l;
              }
           
              int lengthOfLIS(vector<int>& nums) 
              
          {
                  int len = nums.size();
                  vector<int> dp;
                  if(len <= 0) return 0;
                  dp.push_back(nums[0]);
                  for(int i = 1;i < len;i++)
                  {
                      if(nums[i] > dp[dp.size() - 1])
                          dp.push_back(nums[i]);
                      else
                      {
                           //auto it = lower_bound(dp.begin(), dp.end(), nums[i]);
                          //*it = nums[i];
           
                          int p = search(dp,nums[i]);
                          dp[p] = nums[i];
                      }
                  }
           
                   return dp.size();
              }
          };
           
          以下為測(cè)試代碼//
          // 測(cè)試 用例 START
          void test(const char* testName, vector<int>& nums, int expect)
          {
              Solution_1 s1;
              int result1 = s1.lengthOfLIS(nums);
              Solution_2 s2;
              int result2 = s2.lengthOfLIS(nums);
              if (expect == result1 && expect == result2)
                  cout << testName << ", solution passed." << endl;
              else
                  cout << testName << ", solution failed. expect:" << expect << ", result1:" <<result1 << ", result2:" << result2 << endl;
          }
           
          // 測(cè)試用例
          void Test1()
          {
              vector<int> nums = { 10,9,2,5,3,7,101,18 };
              int expect = 4;
              
              test("Test1()", nums, expect);
          }
           
          void Test2()
          {
              vector<int> nums = { 10,11,1,2,3,12,13,4 };
              int expect = 5;
           
              test("Test2()", nums, expect);
          }
           
          NAMESPACE_LENGTHOFLISEND
          // 測(cè)試 用例 END
          //
           
          void LengthOfLIS_Test()
          {
              NAME_LENGTHOFLIS::Test1();
              NAME_LENGTHOFLIS::Test2();
          }


          好了,今天的文章就到這里,如果覺得有所收獲,請(qǐng)順手點(diǎn)個(gè)在看或者轉(zhuǎn)發(fā)吧,你們的支持是我最大的動(dòng)力 。

          上期推文:
          LeetCode1-280題匯總,希望對(duì)你有點(diǎn)幫助!
          LeetCode刷題實(shí)戰(zhàn)281:鋸齒迭代器
          LeetCode刷題實(shí)戰(zhàn)282:給表達(dá)式添加運(yùn)算符
          LeetCode刷題實(shí)戰(zhàn)283:移動(dòng)零
          LeetCode刷題實(shí)戰(zhàn)284:頂端迭代器
          LeetCode刷題實(shí)戰(zhàn)285:二叉搜索樹中的順序后繼
          LeetCode刷題實(shí)戰(zhàn)286:墻和門
          LeetCode刷題實(shí)戰(zhàn)287:尋找重復(fù)數(shù)
          LeetCode刷題實(shí)戰(zhàn)288:?jiǎn)卧~的唯一縮寫
          LeetCode刷題實(shí)戰(zhàn)289:生命游戲
          LeetCode刷題實(shí)戰(zhàn)290:?jiǎn)卧~規(guī)律
          LeetCode刷題實(shí)戰(zhàn)291:?jiǎn)卧~規(guī)律II
          LeetCode刷題實(shí)戰(zhàn)292:Nim 游戲
          LeetCode刷題實(shí)戰(zhàn)293:翻轉(zhuǎn)游戲
          LeetCode刷題實(shí)戰(zhàn)294:翻轉(zhuǎn)游戲II
          LeetCode刷題實(shí)戰(zhàn)295:數(shù)據(jù)流的中位數(shù)
          LeetCode刷題實(shí)戰(zhàn)296:最佳的碰頭地點(diǎn)
          LeetCode刷題實(shí)戰(zhàn)297:二叉樹的序列化與反序列化
          LeetCode刷題實(shí)戰(zhàn)298:二叉樹最長(zhǎng)連續(xù)序列
          LeetCode刷題實(shí)戰(zhàn)299:猜數(shù)字游戲

          瀏覽 112
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美第一精品 | 欧美国家一级a片 | av在线青青草 | 成人先锋AV | 成人免费黄色 |