Maximum index a pointer can reach in N steps by avoiding a given index B – Set 3 (Binary Search)
Given two integers N and B, the task is to print the maximum index a pointer, starting from 0th index can reach in an array of natural numbers(i.e., 0, 1, 2, 3, 4, 5…), say arr[], in N steps without placing itself at index B at any point.
In each step, the pointer can move from the Current Index to a Jumping Index or can remain at the Current Index.
Jumping Index = Current Index + Step Number
Examples:
Input: N = 3, B = 2
Output: 6
Explanation:
Step 1:
Current Index = 0
Step Number = 1
Jumping Index = 0 + 1 = 1
Step 2:Current Index = 1
Step Number = 2
Jumping Index = 1 + 2 = 3
Step 3:
Current Index = 3
Step Number = 3
Jumping Index = 3 + 3 = 6
Therefore, the maximum index that can be reached is 6.
Input: N = 3, B = 1
Output: 5
Explanation:
Step 1:
Current Index = 0
Step Number = 1
Jumping Index = 0 + 1 = 1But this is bad index. So pointer remains at the Current Index.
Step 2:
Current Index = 0
Step Number = 2
Jumping Index = 0 + 2 = 2
Step 3:
Current Index = 2
Step Number = 3
Jumping Index = 2 + 3 = 5
Therefore, the maximum index that can be reached is 5.
Efficient Approach: The naive approach discussed in this article can also be optimized by using Binary Search. If the value of maximumIndex – B exists in the sum of any last K numbers from the first N natural numbers then the maximumIndex can’t be reduced to less than equal to 0 without the jump on index B. therefore, decrement the maximum Index by and perform the above steps again. Follow the steps below to solve the problem:
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int maxIndex( int N, int B)
{
int maximumIndexReached = 0;
vector< int > Ans;
for ( int i = 1; i <= N; i++) {
maximumIndexReached += i;
Ans.push_back(i);
}
reverse(Ans.begin(), Ans.end());
for ( int i = 1; i < ( int )Ans.size(); i++) {
Ans[i] += Ans[i - 1];
}
while (maximumIndexReached) {
auto it
= lower_bound(Ans.begin(), Ans.end(),
maximumIndexReached - B);
if (it == Ans.end()) {
break ;
}
if (*it == maximumIndexReached - B) {
maximumIndexReached--;
}
else {
break ;
}
}
return maximumIndexReached;
}
int main()
{
int N = 3, B = 2;
cout << maxIndex(N, B);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int maxIndex( int N, int B)
{
int maximumIndexReached = 0 ;
Vector<Integer> Ans = new Vector<>();
for ( int i = 1 ; i <= N; i++) {
maximumIndexReached += i;
Ans.add(i+i- 1 );
}
while (maximumIndexReached> 0 ) {
int it
= lower_bound(Ans, maximumIndexReached - B);
if (it == - 1 ) {
break ;
}
if (it == maximumIndexReached - B) {
maximumIndexReached--;
}
else {
break ;
}
}
return maximumIndexReached;
}
public static int lower_bound(Vector<Integer> s, int val)
{
List<Integer> temp = new LinkedList<Integer>();
temp.addAll(s);
Collections.sort(temp);
Collections.reverse(temp);
if (temp.indexOf(val) + 1 == temp.size())
return - 1 ;
else if (temp.get(temp.indexOf(val) + 1 )>val)
return - 1 ;
else
return temp.get(temp.indexOf(val) + 1 );
}
public static void main(String[] args)
{
int N = 3 , B = 2 ;
System.out.print(maxIndex(N, B));
}
}
|
Python3
from bisect import bisect_left
def maxIndex(N, B):
maximumIndexReached = 0
Ans = []
for i in range ( 1 , N + 1 ):
maximumIndexReached + = i
Ans.append(i)
Ans.reverse()
for i in range ( len (Ans)):
Ans[i] + = Ans[i - 1 ]
while (maximumIndexReached):
it = bisect_left(Ans,
maximumIndexReached - B)
if (it not in Ans):
break
if (it = = maximumIndexReached - B):
maximumIndexReached - = 1
else :
break
return maximumIndexReached
if __name__ = = "__main__" :
N = 3
B = 2
print (maxIndex(N, B))
|
C#
using System;
using System.Linq;
using System.Collections.Generic;
class GFG
{
static int maxIndex( int N, int B)
{
int maximumIndexReached = 0;
List< int > Ans = new List< int >();
for ( int i = 1; i <= N; i++)
{
maximumIndexReached += i;
Ans.Add(i + i - 1);
}
while (maximumIndexReached > 0)
{
int it = Ans.Where(x => x <=
maximumIndexReached - B).DefaultIfEmpty(-1).Max();
if (it == -1)
{
break ;
}
if (it == maximumIndexReached - B)
{
maximumIndexReached--;
}
else
{
break ;
}
}
return maximumIndexReached;
}
public static void Main()
{
int N = 3, B = 2;
Console.WriteLine(maxIndex(N, B));
}
}
|
Javascript
<script>
function lowerBound(Ans, target)
{
const targetRange = [-1, -1]
const leftIdx = extremeInsertionIndex(Ans, target, true )
if (leftIdx === Ans.length || Ans[leftIdx] != target)
return targetRange
targetRange[0] = leftIdx
targetRange[1] = extremeInsertionIndex(Ans, target, false ) - 1
return targetRange
function extremeInsertionIndex(Ans, target, left) {
let lo = 0,
hi = Ans.length
while (lo < hi) {
const mid = lo + Math.floor((hi - lo) / 2)
if (Ans[mid] > target || (left && target === Ans[mid]))
hi = mid
else
lo = mid + 1
}
return lo
}
}
function maxIndex(N, B)
{
let maximumIndexReached = 0;
let Ans = [];
for (let i = 1; i <= N; i++) {
maximumIndexReached += i;
Ans.push(i);
}
Ans.reverse();
for (let i = 1; i < Ans.length; i++) {
Ans[i] += Ans[i - 1];
}
while (maximumIndexReached)
{
let it
= lowerBound(Ans, maximumIndexReached - B);
if (it == -1) {
break ;
}
if (it == maximumIndexReached - B) {
maximumIndexReached--;
}
else {
break ;
}
}
return maximumIndexReached;
}
let N = 3, B = 2;
document.write(maxIndex(N, B));
</script>
|
Time Complexity: O(N*log N)
Auxiliary Space: O(N)
Last Updated :
14 Feb, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...