📜  查找子数组是否为山脉形式

📅  最后修改于: 2021-04-17 11:54:43             🧑  作者: Mango

给定一个整数数组和一个范围,我们需要查找落入该范围的子数组是否具有山峰形式的值。如果所有值都是递增或递减的,或者先递增然后递减的,则子数组的所有值都称为山的形式。
如果存在整数K,1 <= K <= N,更正式地说,子数组[a1,a2,a3…aN]可以说是山的形式,
a1 <= a2 <= a3 .. <= aK> = a(K + 1)> = a(K + 2)…。 > = aN
例子:

Input : Arr[]  = [2 3 2 4 4 6 3 2], Range = [0, 2]
Output :  Yes

Explanation: The output is yes , subarray is [2 3 2], 
so subarray first increases and then decreases

Input:  Arr[] = [2 3 2 4 4 6 3 2], Range = [2, 7]
Output: Yes

Explanation: The output is yes , subarray is [2 4 4 6 3 2], 
so subarray first increases and then decreases


Input: Arr[]= [2 3 2 4 4 6 3 2], Range = [1, 3]
Output: no

Explanation: The output is no, subarray is [3 2 4], 
so subarray is not in the form above stated

解决方案:

  • 方法:问题有多个查询,因此对于每个查询,应以尽可能少的时间复杂性来计算解决方案。因此,请创建两个额外的空格,其长度与原始数组的长度相同。对于每个元素,找到左侧的最后一个索引,该索引增加(即大于其前一个元素),找到右侧的元素,将在右侧存储第一个索引,该索引减小(即大于其下一个元素)。如果可以在恒定时间内为每个索引计算这些值,那么对于每个给定范围,可以在恒定时间内给出答案。
  • 算法:
    1. 创建两个长度为n的额外空格,分别为leftright,以及一个额外的变量lastptr
    2. 初始化left [0] = 0和lastptr = 0
    3. 从第二个索引到末尾遍历原始数组
    4. 对于每个索引,检查它是否大于上一个元素,如果是,则使用当前索引更新lastptr
    5. 对于每个索引,将lastptr存储在left [i]中
    6. 初始化right [N-1] = N-1和lastptr = N-1
    7. 从倒数第二个索引开始遍历原始数组
    8. 对于每个索引,检查它是否大于下一个元素,如果是,则使用当前索引更新lastptr
    9. 对于每个索引,将lastptr存储在right [i]中
    10. 现在处理查询
    11. 对于每个查询l,r ,如果right [l]> = left [r],则输出yes否则no
  • 执行:
    C/C++
    // C++ program to check whether a subarray is in
    // mountain form or not
    #include 
    using namespace std;
      
    // Utility method to construct left and right array
    int preprocess(int arr[], int N, int left[], int right[])
    {
        // Initialize first left index as that index only
        left[0] = 0;
        int lastIncr = 0;
      
        for (int i = 1; i < N; i++)
        {
            // if current value is greater than previous,
            // update last increasing
            if (arr[i] > arr[i - 1])
                lastIncr = i;
            left[i] = lastIncr;
        }
      
        // Initialize last right index as that index only
        right[N - 1] = N - 1;
        int firstDecr = N - 1;
      
        for (int i = N - 2; i >= 0; i--)
        {
            // if current value is greater than next,
            // update first decreasing
            if (arr[i] > arr[i + 1])
                firstDecr = i;
            right[i] = firstDecr;
        }
    }
      
    // Method returns true if arr[L..R] is in mountain form
    bool isSubarrayMountainForm(int arr[], int left[],
                                 int right[], int L, int R)
    {
        // return true only if right at starting range is
        // greater than left at ending range
        return (right[L] >= left[R]);
    }
      
    //    Driver code to test above methods
    int main()
    {
        int arr[] = {2, 3, 2, 4, 4, 6, 3, 2};
        int N = sizeof(arr) / sizeof(int);
      
        int left[N], right[N];
        preprocess(arr, N, left, right);
      
        int L = 0;
        int R = 2;
        if (isSubarrayMountainForm(arr, left, right, L, R))
            cout << "Subarray is in mountain form\n";
        else
            cout << "Subarray is not in mountain form\n";
      
        L = 1;
        R = 3;
        if (isSubarrayMountainForm(arr, left, right, L, R))
            cout << "Subarray is in mountain form\n";
        else
            cout << "Subarray is not in mountain form\n";
      
        return 0;
    }


    Java
    // Java program to check whether a subarray is in
    // mountain form or not
    class SubArray
    {
        // Utility method to construct left and right array
        static void preprocess(int arr[], int N, int left[], int right[])
        {
            // initialize first left index as that index only
            left[0] = 0;
            int lastIncr = 0;
          
            for (int i = 1; i < N; i++)
            {
                // if current value is greater than previous,
                // update last increasing
                if (arr[i] > arr[i - 1])
                        lastIncr = i;
                left[i] = lastIncr;
            }
          
            // initialize last right index as that index only
            right[N - 1] = N - 1;
            int firstDecr = N - 1;
          
            for (int i = N - 2; i >= 0; i--)
            {
                // if current value is greater than next,
                // update first decreasing
                if (arr[i] > arr[i + 1])
                        firstDecr = i;
                right[i] = firstDecr;
            }
        }
          
        // method returns true if arr[L..R] is in mountain form
        static boolean isSubarrayMountainForm(int arr[], int left[],
                                        int right[], int L, int R)
        {
            // return true only if right at starting range is
            // greater than left at ending range
            return (right[L] >= left[R]);
        }
          
        public static void main(String[] args)
        {
            int arr[] = {2, 3, 2, 4, 4, 6, 3, 2};
            int N = arr.length;
            int left[] = new int[N];
            int right[] = new int[N];
            preprocess(arr, N, left, right);
            int L = 0;
            int R = 2;
              
            if (isSubarrayMountainForm(arr, left, right, L, R))
                System.out.println("Subarray is in mountain form");
            else
                System.out.println("Subarray is not in mountain form");
          
            L = 1;
            R = 3;
          
            if (isSubarrayMountainForm(arr, left, right, L, R))
                System.out.println("Subarray is in mountain form");
            else
                System.out.println("Subarray is not in mountain form");
        }
    }
    // This Code is Contributed by Saket Kumar


    Python3
    # Python 3 program to check whether a subarray is in
    # mountain form or not
      
    # Utility method to construct left and right array
    def preprocess(arr, N, left, right):
        # initialize first left index as that index only
        left[0] = 0
        lastIncr = 0
      
        for i in range(1,N):
            # if current value is greater than previous,
            # update last increasing
            if (arr[i] > arr[i - 1]):
                lastIncr = i
            left[i] = lastIncr
      
        # initialize last right index as that index only
        right[N - 1] = N - 1
        firstDecr = N - 1
      
        i = N - 2
        while(i >= 0):
            # if current value is greater than next,
            # update first decreasing
            if (arr[i] > arr[i + 1]):
                firstDecr = i
            right[i] = firstDecr
            i -= 1
      
    # method returns true if arr[L..R] is in mountain form
    def isSubarrayMountainForm(arr, left, right, L, R):
          
        # return true only if right at starting range is
        # greater than left at ending range
        return (right[L] >= left[R])
      
    # Driver code 
    if __name__ == '__main__':
        arr = [2, 3, 2, 4, 4, 6, 3, 2]
        N = len(arr)
      
        left = [0 for i in range(N)]
        right = [0 for i in range(N)]
        preprocess(arr, N, left, right)
      
        L = 0
        R = 2
        if (isSubarrayMountainForm(arr, left, right, L, R)):
            print("Subarray is in mountain form")
        else:
            print("Subarray is not in mountain form")
      
        L = 1
        R = 3
        if (isSubarrayMountainForm(arr, left, right, L, R)):
            print("Subarray is in mountain form")
        else:
            print("Subarray is not in mountain form")
      
    # This code is contributed by
    # Surendra_Gangwar


    C#
    // C# program to check whether 
    // a subarray is in mountain 
    // form or not
    using System;
      
    class GFG
    {
          
        // Utility method to construct 
        // left and right array
        static void preprocess(int []arr, int N, 
                               int []left, int []right)
        {
            // initialize first left 
            // index as that index only
            left[0] = 0;
            int lastIncr = 0;
          
            for (int i = 1; i < N; i++)
            {
                // if current value is 
                // greater than previous,
                // update last increasing
                if (arr[i] > arr[i - 1])
                        lastIncr = i;
                left[i] = lastIncr;
            }
          
            // initialize last right 
            // index as that index only
            right[N - 1] = N - 1;
            int firstDecr = N - 1;
          
            for (int i = N - 2; i >= 0; i--)
            {
                // if current value is 
                // greater than next,
                // update first decreasing
                if (arr[i] > arr[i + 1])
                        firstDecr = i;
                right[i] = firstDecr;
            }
        }
          
        // method returns true if
        // arr[L..R] is in mountain form
        static bool isSubarrayMountainForm(int []arr, int []left,
                                           int []right, int L, int R)
        {
            // return true only if right at 
            // starting range is greater 
            // than left at ending range
            return (right[L] >= left[R]);
        }
          
          
        // Driver Code
        static public void Main ()
        {
            int []arr = {2, 3, 2, 4,
                         4, 6, 3, 2};
            int N = arr.Length;
            int []left = new int[N];
            int []right = new int[N];
            preprocess(arr, N, left, right);
              
            int L = 0;
            int R = 2;
              
            if (isSubarrayMountainForm(arr, left, 
                                       right, L, R))
                Console.WriteLine("Subarray is in " + 
                                    "mountain form");
            else
                Console.WriteLine("Subarray is not " + 
                                  "in mountain form");
          
            L = 1;
            R = 3;
          
            if (isSubarrayMountainForm(arr, left, 
                                       right, L, R))
                Console.WriteLine("Subarray is in " + 
                                    "mountain form");
            else
                Console.WriteLine("Subarray is not " + 
                                  "in mountain form");
        }
    }
      
    // This code is contributed by aj_36


  • 输出:
    Subarray is in mountain form
    Subarray is not in mountain form
    
  • 复杂度分析:
    • 时间复杂度: O(n)。
      仅需要两个遍历,因此时间复杂度为O(n)。
    • 空间复杂度: O(n)。
      需要两个长度为n的额外空间,因此空间复杂度为O(n)。