Given an integer array arr[] representing a sequence of elevations, Return an array that includes:
The first and last elements of the array.
Every element where the trend of the sequence changes that is, where the direction of change switches from increasing to decreasing or from decreasing to increasing.
Note: Consecutive equal elements (flat segments) should be treated as a single elevation and ignored for detecting direction changes.
Input: arr[] = [6, 4, 2, -2, 5, 3, 2, 2, -1, -1, 4] Output: [6, -2, 5, -1, 4] Explanation: Starts from 6 goes down to -2, -2 is the breaking point then 5, 5 is the breaking point then from 5 goes down to -1, -1 is breaking point then 4.
Input: arr[] = [6, 10, 11, 13] Output: [6, 13] Explanation: 6 is the starting point and 13 is last point.
Input: arr[] = [1, 1] Output: [1] Explanation: Since we start from 1 but do not move further.
[Approach] Traversal with Turning Point Detection - O(n) Time and O(1) Space
The idea is to follow the changes in elevation as we move through the array. We start by adding the first point. Then, for each point, we check if it forms a peak or a valley—that means the direction of the trail is changing there. If it does, we include it. At the end, we add the last point if it’s not already there. This way, we keep only the important turning points and ignore the flat or straight parts.
C++
#include<iostream>#include<vector>usingnamespacestd;vector<int>extractPoints(vector<int>&arr){intn=arr.size();vector<int>ans;if(n==0)returnans;ans.push_back(arr[0]);for(inti=1;i<n-1;i++){// check for a peak: strictly greater // than both the last added and the next elementif(arr[i]>ans.back()&&arr[i]>arr[i+1]){ans.push_back(arr[i]);}// check for strictly smaller than // both the last added and the next elementelseif(ans.back()>arr[i]&&arr[i]<arr[i+1]){ans.push_back(arr[i]);}}// include the last point if it is // different from the last added pointif(ans.back()!=arr[n-1]){ans.push_back(arr[n-1]);}returnans;}intmain(){vector<int>arr={6,4,2,-2,5,3,2,2,-1,-1,4};vector<int>result=extractPoints(arr);for(inti=0;i<result.size();i++){cout<<result[i]<<" ";}return0;}
Java
importjava.util.ArrayList;classGfG{publicstaticArrayList<Integer>extractPoints(int[]arr){intn=arr.length;ArrayList<Integer>ans=newArrayList<>();if(n==0)returnans;// Always include the first pointans.add(arr[0]);for(inti=1;i<n-1;i++){// check for a peak: strictly greater // than both the last added and the next elementif(arr[i]>ans.get(ans.size()-1)&&arr[i]>arr[i+1]){ans.add(arr[i]);}// check for a valley: strictly smaller // than both the last added and the next elementelseif(ans.get(ans.size()-1)>arr[i]&&arr[i]<arr[i+1]){ans.add(arr[i]);}}// include the last point if it is // different from the last added pointif(ans.get(ans.size()-1)!=arr[n-1]){ans.add(arr[n-1]);}returnans;}publicstaticvoidmain(String[]args){int[]arr={6,4,2,-2,5,3,2,2,-1,-1,4};ArrayList<Integer>result=extractPoints(arr);for(intval:result){System.out.print(val+" ");}}}
Python
defextractPoints(arr):n=len(arr)result=[]ifn==0:returnresult# Always include the first pointresult.append(arr[0])foriinrange(1,n-1):# check for a peak: strictly greater # than both the last added and the next elementifarr[i]>result[-1]andarr[i]>arr[i+1]:result.append(arr[i])# check for a valley: strictly smaller # than both the last added and the next elementelifresult[-1]>arr[i]andarr[i]<arr[i+1]:result.append(arr[i])# include the last point if it is # different from the last added pointifresult[-1]!=arr[-1]:result.append(arr[-1])returnresultif__name__=="__main__":arr=[6,4,2,-2,5,3,2,2,-1,-1,4]print(*extractPoints(arr))
C#
usingSystem;usingSystem.Collections.Generic;classGfG{publicList<int>extractPoints(int[]arr){intn=arr.Length;List<int>result=newList<int>();if(n==0)returnresult;// always include the first pointresult.Add(arr[0]);for(inti=1;i<n-1;i++){// check for a peak: strictly greater // than both the last added and the next elementif(arr[i]>result[result.Count-1]&&arr[i]>arr[i+1]){result.Add(arr[i]);}// check for a valley: strictly smaller // than both the last added and the next elementelseif(result[result.Count-1]>arr[i]&&arr[i]<arr[i+1]){result.Add(arr[i]);}}// include the last point if it is // different from the last added pointif(result[result.Count-1]!=arr[n-1]){result.Add(arr[n-1]);}returnresult;}staticvoidMain(){int[]arr={6,4,2,-2,5,3,2,2,-1,-1,4};GfGobj=newGfG();List<int>result=obj.extractPoints(arr);foreach(intvalinresult){Console.Write(val+" ");}}}
JavaScript
functionextractPoints(arr){constn=arr.length;constresult=[];if(n===0)returnresult;// Always include the first pointresult.push(arr[0]);for(leti=1;i<n-1;i++){// check for a peak: strictly greater // than both the last added and the next elementif(arr[i]>result[result.length-1]&&arr[i]>arr[i+1]){result.push(arr[i]);}// check for a valley: strictly smaller // than both the last added and the next elementelseif(result[result.length-1]>arr[i]&&arr[i]<arr[i+1]){result.push(arr[i]);}}// include the last point if it is // different from the last added pointif(result[result.length-1]!==arr[n-1]){result.push(arr[n-1]);}returnresult;}// Driver Codeconstarr=[6,4,2,-2,5,3,2,2,-1,-1,4];constresult=extractPoints(arr);console.log(...result);