leetcode (300)는 가장 긴은 서브 시퀀스는 동적 프로그래밍의 가장 긴 연속 상승 증가

leetcode (300)는 가장 긴은 서브 시퀀스가 ​​가장 긴 연속 상승 증가

leetcode 년 3 월 2020 매일 질문 펀치
화웨이는이 질문을 말한다

질문 :
소정 정수 배열 장애, 상기 최장 발견 상승 시퀀스의 길이.
예 :
입력 [10,9,2,5,3,7,101,18]
출력 : 4
설명 : 가장 긴 시퀀스는 [2,3,7,101 같이, 길이가 4 인 증가된다.
참고 : 긴 상승 시퀀스의 다양한 조합이있을 수 있습니다, 당신은 단지 해당하는 길이를 출력해야합니다. 알고리즘의 시간 복잡도는 O (N2)를해야한다.
고급 : 당신이 O로 알고리즘의 시간 복잡도를 감소 (N N 로그) 할 수 있습니까?

원래 제목 링크 : HTTPS : //leetcode-cn.com/problems/longest-increasing-subsequence

지식 : 동적 프로그래밍

문제 해결 규칙을 해결하기에 적합합니다 :

  1. 최적의 하부에 문제가 있음.
  2. 더 후 효과, 최적의 솔루션을 찾을 멀티 손가락 없습니다.

게이지 문제 해결 아이디어를 이동 :

  1. 하위 분할 문제
  2. 상태를 확인합니다
  3. 상태 천이를 결정 방정식
  4. 시작 조건 또는 경계 조건을 결정

재귀 룰 변경 재귀 함수는 N 차원 배열로, 상기 n 개의 매개 변수를 포함하는, 저장된 값은 재귀 함수의 리턴 값이 동일하다.

사고 : 파이썬 동적 프로그래밍, 아이 [I]는 i 번째 요소의 순서를 나타내는 nums 증가 서브 시퀀스 길이의 끝에서 최장. 하위 문제 : i 번째 요소를 해결하기 전에 시퀀스에서 가장 긴 서브 - 상승 길이이다. 상태 : 아이 [I]. 상태 전이 식 : 이전의 모든 요소 nums [J]을 통해 각각의 서브 - 질문, 만약 nums [J] <nums [I ]은, 아이 [I]은 모든 자식 [J] +1의 최대 값과 동일하다. 경계 조건 : 1의 시작 값. 시간 복잡도 : 연산 상태 필요의 O (n)은 시간 전의 상태를 통과 할 때, 총 시간 복잡도는 O (N ^ 2) 그래서 O (N ^ 2), 동적 프로그래밍 상태의 수는 N이다. 공간 복잡도 : O (N)으로 인해 길이 n의 배열의 추가적인 사용.

세부 사항 :

  1. nums를 비어 제외
  2. best_i 1로 설정되어 시작 값은 0이 될 수 없다

코드 :

class Solution(object):
    def lengthOfLIS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        # 动态规划 O(N^2)
        child=[] # child[i]表示以nums里第i个元素结尾的序列里最长上升子序列的长度
        if nums == []:
            return 0
        child.append(1)
        for i in range(1,len(nums)):
            best_i=1
            for j in range(0,i):
                if nums[i]>nums[j]:
                    tem=child[j]+1
                    if tem>best_i:
                        best_i=tem
            child.append(best_i)
        return max(child)

방법 2 : 욕심 +이진 검색: 참조 공식 설명을 . 욕심이 알고리즘의 핵심 아이디어는 지역 최적를 찾는 것입니다. 시간 복잡도 O (NlogN). 이 질문은 출력의 길이이고,이 방법 대신에 사용될 수 있고, 이러한 시퀀스가 출력되도록, 그렇게 할 수 없다.

class Solution(object):
    def lengthOfLIS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        # 贪心+二分查找 O(NlogN)
        if nums == []:
            return 0
        tail=[nums[0]] # 存长度最长上升子序列的最后一个元素值
        len=1 # 最长上升子序列的长度
        
        for num in nums[1:]:
            if num>tail[len-1]:
                tail.append(num)
                len+=1
            else:
                # 二分查找比num大的最小的元素及位置
                l=0
                r=len-1
                while l<r:
                    mid = int((l+r)/2)
                    if tail[mid] == num:
                        l=mid
                        break
                    if tail[mid]<num:
                        l=mid+1
                        continue
                    elif tail[mid]>num:
                        r=mid
                        continue
                tail[l]=num
            
        return len

PS. 두 번째 방법은 전형적인없고, 제 초점 알.
이 블로그는 감사합니다,이 문서에 링크를 첨부, 소스를 표시하시기 바랍니다,지도 환영, 복제, 원래 작업

게시 20 개 원래 기사 · 원 찬양 한 · 전망 (206)

추천

출처blog.csdn.net/weixin_43973433/article/details/104856044