[leetcode] - 최대 하위 순서 와 (leetcode 53)

9501 단어 알고리즘leetcode
최대 하위 순서 와
정수 배열 nums 를 지정 하고 최대 와 연속 하위 배열 (하위 배열 은 최소 하나의 요 소 를 포함 합 니 다) 을 찾 아 최대 와 합 을 되 돌려 줍 니 다.
  • 예시:
  • 입력: [- 2, 1, - 3, 4, - 1, 2, 1, - 5, 4],
    출력: 6
    해석: 연속 서브 배열 [4, - 1, 2, 1] 의 것 과 최대, 6.
    분 치 법
  • 사고방식:
    원 배열 을 좌우 두 부분 으로 나 누고 요소 수 는 n / 2 이 며 가장 큰 하위 배열 의 아래 를 i 로 표시 하고 j 는 i 와 j 의 상황 을 세 가지 로 나 누 었 다.
  • i, j 는 모두 원수 조 의 왼쪽, 즉 low < = i < = j < = mid
  • 에 속한다.
  • i, j 는 모두 원수 조 의 반 측, 즉 mid
  • 에 속한다.
  • i, j 는 mid 점, 즉 low < = i < = mid
  • 를 뛰 어 넘 었 다.
    상기 세 가지 상황 에 따라 분 치 전략 을 구축 하고 왼쪽 부분의 최대 서브 배열, 오른쪽 부분의 최대 서브 배열 과 mid 를 뛰 어 넘 는 최대 서브 배열 을 비교 한 다음 에 상기 세 개의 최대 서브 배열 을 비교 하여 최대 치 를 취한 다. 즉, 주어진 배열 의 최대 서브 배열 이다.
  • 위조 코드:
    //    mid      
    //  i,j  mid,           mid,          mid+1
    FIND-MAX-CROSSING-SUBARRAY(A,low,mid,high)
        //  mid        
        left-sum=MIN //       
        sum=0
        max-left//    
        for i=mid to low
            sum=A[i]+sum
            if sum>left-sum
                max-left=i
                left-sum=sum
    
        //  mid        
        right-sum=MIN
        sum=0
        max-right
        for j=mid+1 to high
            sum=A[j]+sum
            if sum>right-sum
                max-right=j
                right-sum=sum
        return(max-left,max-right,left-sum+right-sum)
    
    //   A      
    FIND-MAXIMUM-SUBARRAY(A,low,high)
        if low==high
            return(low,high,A[low])//         ,           
        else
            mid=(low+high)/2
            (left-low,left-high,left-sum)=FIND-MAXIMUM-SUBARRAY(A,low,mid)
            (right-low,right-high,right-sum)=FIND-MAXIMUM-SUBARRAY(A,mid+1,high)
            (corss-low,cross-high,cross-sum)=FIND-MAX-CROSSING-SUBARRAY(A,low,mid,high)
            if left-sum>right-sum and left-sum>corss-sum
                return (left-low,left-high,left-sum)
            else if right-sum>left-sum and right-sum>corss-sum
                return (right-low,right-high,right-sum)
            else
                return (cross-low,cross-high,cross-sum)
  • 시간 복잡 도 분석: mid 를 뛰 어 넘 는 최대 서브 배열 의 일부 시간 복잡 도 는?Θ(n), 분해 부분의 시간 복잡 도가 상수 이면 T (n) = 2T (n / 2) +Θ(n), 즉 T (n) =Θ(nlgn)
  • 소스 코드 실현:
    #include 
    #include 
    #include 
    using namespace std;
    typedef tuple resultType;
    resultType FindMaxCrossSubarray
        (int *A,int low,int mid,int high)
    {
        int left_max =mid;
        long long leftMaxSum = LLONG_MIN;
        long long sum=0;
        for(int i = mid;i>=low;--i)
        {
            sum=sum+A[i];
            if(sum>leftMaxSum)
            {
                left_max = i;
                leftMaxSum = sum;
            }
        }
    
        int right_max = mid+1;
        long long rightMaxSum=LLONG_MIN;
        sum = 0;
        for(int j=mid+1;j<=high;++j)
        {
            sum=sum+A[j];
            if(sum>rightMaxSum)
            {
                right_max = j;
                rightMaxSum = sum;
            }
        }
        return {left_max,right_max,leftMaxSum+rightMaxSum};
    }
    
    resultType FindMaxSubArray(int *A,int low,int high)
    {
        if(low == high)
        {
            return {low,high,A[low]};
        }
        else
        {
            int mid = (low+high)/2;
            resultType leftResult = FindMaxSubArray(A,low,mid);
            resultType rightResult = FindMaxSubArray(A,mid+1,high);
            resultType crossResult = FindMaxCrossSubarray(A,low,mid,high);
            if(get<2>(leftResult)>get<2>(rightResult)&&get<2>(leftResult)>get<2>(crossResult))
            {
                return leftResult;
            }
            else if(get<2>(rightResult)>get<2>(leftResult)&&get<2>(rightResult)>get<2>(crossResult))
            {
                return rightResult;
            }
            else
            {
                return crossResult;
            }  
        } 
    }
    
    int main()
    {
        int test[9]{-2,1,-3,4,-1,2,1,-5,4};
        resultType result = FindMaxSubArray(test,0,sizeof(test)/sizeof(int)-1);
        for(int i=get<0>(result);i<=get<1>(result);i++)
        {
            cout<(result);
        system("pause");
        return 0;
    }
  • 분 치 법 최적화
  • 계산 이 mid 를 뛰 어 넘 는 가장 큰 하위 배열 을 바 꾸 는 방법 이다.[l... r] 이 구간 의 최대 하위 그룹 은 [l... m] 의 최대 하위 그룹 과 [m + 1. r] 의 최대 하위 그룹 또는 m 와 m + 1 을 포함 하 는 최대 하위 그룹 (즉 mid 를 뛰 어 넘 는 것) 일 수 있 습 니 다.네 개의 양 을 통계 하면 각각 다음 과 같다.
  • lsum: l 로 시작 하 는 최대 하위 그룹
  • rsum: r 로 끝 나 는 최대 하위 그룹
  • isum: 현재 모든 원소 의 합
  • msum: 현재 최대 하위 그룹
  • 은 합병 할 때 왼쪽, 오른쪽 양쪽 의 통 계량 에 따라 합병 후의 통 계량 을 업데이트 하고 최종 적 으로 얻 은 msum 은 가장 큰 하위 배열 이다.업데이트 규칙
  • 합병 후의 lsum 은 왼쪽 에 있 는 하위 문자열 의 lsum 또는 왼쪽 에 있 는 하위 문자열 의 isum 에 오른쪽 에 있 는 하위 문자열 의 lsum 을 더 하여 비교적 큰 값 을 합병 후의 lsum
  • 으로 한다.
  • 합 병 된 rsum 은 오른쪽 하위 문자열 의 rsum 또는 오른쪽 하위 문자열 의 isum 에 왼쪽 하위 문자열 의 rsum 을 더 하여 비교적 큰 값 을 합 친 rsum
  • 으로 한다.
  • 합병 후의 isum 은 좌우 양측 isum 의 합
  • 합병 후의 msum 은 왼쪽 의 msum 또는 오른쪽 의 msum 또는 왼쪽 의 rsum 에 오른쪽 lsum 세 가 지 를 더 하면 최대 치 를 새로운 msum
  • 으로 취한 다.
  • 위조 코드 실현:
    FIND-MAX-SUBARRAY(A,low,high)
        if low==high
            return (A[low],A[low],A[low],A[low])//      lsum,rsum,isum,msum
        else
            mid = (low+high)/2
            (l_lsum,l_rsum,l_isum,l_msum)=FIND-MAX-SUBARRAY(A,low,mid)
            (r_lsum,r_rsum,r_isum,r_msum)=FIND-MAX-SUBARRAY(A,mid+1,high)
            lsum=l_lsum>(l_isum+r_lsum) ? l_lsum :l_isum+r_lsum
            rsum=r_rsum>(r_isum+l_rsum) ? r_rsum:r_isum+l_rsum
            isum=l_isum+r_isum
            if l_msum>r_msum and l_msum>(l_rsum+r_lsum)
                return (lsum,rsum,isum,l_msum)
            if r_msum>l_msum and r_msum>(l_rsum+r_lsum)
                return (lsum,rsum,isum,r_msum)
            else
                return (lsum,rsum,isum,l_rsum+r_lsum)
  • 시간 복잡 도 분석: 분해 부분의 시간 복잡 도 는 상수 이 고 합병 부분의 시간 복잡 도도 상수 이다.T (n) = 2T (n / 2) +Θ(1), 즉 T (n) =Θ(lgn)
  • 소스 코드 실현: 다음 소스 코드 가 구 한 최대 하위 배열 의 합, 최대 하위 배열 에 대응 하 는 아래 표 시 를 저장 하지 않 았 습 니 다
    #include 
    #include 
    
    using namespace std;
    
    using resultType = tuple;
    
    resultType FindMaxSubArray(int *A,int low,int high)
    {
        if(low==high)
        {
            return {A[low],A[low],A[low],A[low]};
        }
        else
        {
            int mid = (low+high)/2;
            resultType lResult =FindMaxSubArray(A,low,mid);
            resultType rResult =FindMaxSubArray(A,mid+1,high);
            int l_lsum = get<0>(lResult),
            l_rsum = get<1>(lResult),
            l_isum = get<2>(lResult),
            l_msum = get<3>(lResult);
            int r_lsum = get<0>(rResult),
            r_rsum = get<1>(rResult),
            r_isum = get<2>(rResult),
            r_msum = get<3>(rResult);
            int lsum = l_lsum > (l_isum+r_lsum) ? l_lsum :l_isum+r_lsum;
            int rsum = r_rsum > (r_isum+l_rsum) ? r_rsum:r_isum+l_rsum;
            int isum = l_isum+r_isum;
            if(l_msum>r_msum && l_msum>(l_rsum+r_lsum))
            {
                return {lsum,rsum,isum,l_msum};
            }      
            else if(r_msum>l_msum && r_msum>(l_rsum+r_lsum))
            {
                return {lsum,rsum,isum,r_msum};
            }
            else
            {
                return {lsum,rsum,isum,l_rsum+r_lsum};
            }        
        }
    }
    int GetMaxSubArrayValue(int *A,int low,int high)
    {
        resultType result = FindMaxSubArray(A,low,high);
        return get<3>(result);
    }
    
    int main()
    {
        int test[9]{-2,1,-3,4,-1,2,1,-5,4};
        int result = GetMaxSubArrayValue(test,0,sizeof(test)/sizeof(int)-1);
        cout<
  • 최대 하위 그룹 문제 욕심 법 풀이
  • 만약 에 배열 A [1... j] 의 최대 배열 을 알 고 있다 면 A [1... j + 1] 의 최대 서브 배열 은 A [1.. j] 의 서브 배열 이거 나 j + 1 을 마지막 요소 로 하 는 서브 배열 이다.j + 1 을 마지막 으로 하 는 하위 배열 은 두 가지 가 있 는데 하 나 는 j + 1 위치 에 있 는 요소 만 포함 하고 다른 하 나 는 j + 1 전의 하위 서열 에 j + 1 을 추가 하 는 것 이다.만약 에 j + 1 전의 하위 서열 과 정수 라면 이전의 하위 서열 을 포함 하 는 배열 요소 와 j + 1 위치 요소 만 포함 하 는 배열 보다 크다.이런 사고방식 에 따라 왼쪽 에서 오른쪽으로 배열 을 옮 겨 다 니 면 가장 큰 하위 그룹
  • 을 얻 을 수 있다.
  • 위조 코드:
    FIND-MAX-SUBARRAY(A,low,high)
        cursum=MIN//           
        curleft=0//                      
        maxsum=MIN//             
        maxleft=0//                 
        maxright=0//                 
        for i=low to high
            if cursum<0
                cursum=A[i]
                curleft=i
            else
                cursum=cursum+A[i]
            if cursum>maxsum
                maxsum=cursum
                maxleft=curleft
                maxright=i
        return (maxsum,maxleft,maxright)
  • 시간 복잡 도 분석: 한 번 만 옮 겨 다 니 고 시간 복잡 도 는?Θ(n)
  • 소스 코드 실현:
    #include 
    #include 
    #include 
    using namespace std;
    
    using ResultType=tuple;
    ResultType FindMaxSubArray(int *A,int low,int high)
    {
        long long cursum =  LLONG_MIN;
        int curleft = 0;
        long long maxsum = LLONG_MIN;
        int maxleft = 0;
        int maxright = 0;
        for(int n=low;n<=high;++n)
        {
            if(cursum<0)
            {
                cursum=A[n];
                curleft=n;
            }
            else
            {
                cursum+=A[n];
            }
            if(cursum>maxsum)
            {
                maxsum = cursum;
                maxleft = curleft;
                maxright = n;
            }
        }
        return {maxsum,maxleft,maxright};
    }
    int main()
    {
        int test[9]{-2,1,-3,4,-1,2,1,-5,4};
        ResultType result = FindMaxSubArray(test,0,sizeof(test)/sizeof(int)-1);
        for(int i=get<1>(result);i<=get<2>(result);i++)
        {
            cout<(result);
        system("pause");
        return 0;
    }
  • 좋은 웹페이지 즐겨찾기