用最少的步骤找到一个数字

给定一条从-无穷大到+无穷大的无穷数线,我们就在零上。我们可以在每第n次移动n步。

null

方法1:使用树

1st time; we can move only 1 step to both ways, means -1 1;2nd time we can move 2 steps  from -1 and 1;-1 :  -3 (-1-2)  1(-1+2) 1 :  -1 ( 1-2)  3(1+2)3rd time we can move 3 steps either way from -3, 1, -1, 3 -3:  -6(-3-3) 0(-3+3)1:   -2(1-3)   4(1+3)-1:  -4(-1-3)  2(-1+3)3:     0(0-3)   6(3+3) Find the minimum number of steps to reach a given number n.

例如:

Input : n = 10Output : 4We can reach 10 in 4 steps,  1, 3, 6, 10 Input : n = 13Output : 5We can reach 10 in 4 steps,  -1, 2, 5, 9, 14

这个问题可以建模为树。我们把初始点0放在根上,1和-1作为根的子元素。下一级包含距离为2的值,依此类推。

              0            /            -1       1          /       /         1   -3   -1   3     /    /   /   / 

现在的问题是找到值为n的根节点 水平顺序遍历 以查找最近的节点。请注意,对最近的节点使用DFS从来都不是一个好主意(我们可能会降低许多不必要的级别)。

以下是C++、Python实现上述思想。

C++

// C++ program to find a number in minimum steps
#include <bits/stdc++.h>
using namespace std;
#define InF 99999
// To represent data of a node in tree
struct number {
int no;
int level;
public :
number() {}
number( int n, int l)
: no(n), level(l)
{
}
};
// Prints level of node n
void findnthnumber( int n)
{
// Create a queue and insert root
queue<number> q;
struct number r(0, 1);
q.push(r);
// Do level order traversal
while (!q.empty()) {
// Remove a node from queue
struct number temp = q.front();
q.pop();
// To avoid infinite loop
if (temp.no >= InF || temp.no <= -InF)
break ;
// Check if dequeued number is same as n
if (temp.no == n) {
cout << "Found number n at level "
<< temp.level - 1;
break ;
}
// Insert children of dequeued node to queue
q.push(number(temp.no + temp.level, temp.level + 1));
q.push(number(temp.no - temp.level, temp.level + 1));
}
}
// Driver code
int main()
{
findnthnumber(13);
return 0;
}


JAVA

// Java program to find a number in minimum steps
import java.util.*;
class GFG
{
static final int InF = 99999 ;
// To represent data of a node in tree
static class number
{
int no;
int level;
number() {}
number( int n, int l)
{
this .no = n;
this .level = l;
}
};
// Prints level of node n
static void findnthnumber( int n)
{
// Create a queue and insert root
Queue<number> q = new LinkedList<>();
number r = new number( 0 , 1 );
q.add(r);
// Do level order traversal
while (!q.isEmpty())
{
// Remove a node from queue
number temp = q.peek();
q.remove();
// To astatic void infinite loop
if (temp.no >= InF || temp.no <= -InF)
break ;
// Check if dequeued number is same as n
if (temp.no == n)
{
System.out.print( "Found number n at level "
+ (temp.level - 1 ));
break ;
}
// Insert children of dequeued node to queue
q.add( new number(temp.no + temp.level, temp.level + 1 ));
q.add( new number(temp.no - temp.level, temp.level + 1 ));
}
}
// Driver code
public static void main(String[] args)
{
findnthnumber( 13 );
}
}
// This code is contributed by gauravrajput1


Python3

from collections import deque
# Python program to find a number in minimum steps
InF = 99999
# To represent data of a node in tree
class number:
def __init__( self ,n,l):
self .no = n
self .level = l
# Prints level of node n
def findnthnumber(n):
# Create a queue and insert root
q = deque()
r = number( 0 , 1 )
q.append(r)
# Do level order traversal
while ( len (q) > 0 ):
# Remove a node from queue
temp = q.popleft()
# q.pop()
# To avoid infinite loop
if (temp.no > = InF or temp.no < = - InF):
break
# Check if dequeued number is same as n
if (temp.no = = n):
print ( "Found number n at level" , temp.level - 1 )
break
# Insert children of dequeued node to queue
q.append(number(temp.no + temp.level, temp.level + 1 ))
q.append(number(temp.no - temp.level, temp.level + 1 ))
# Driver code
if __name__ = = '__main__' :
findnthnumber( 13 )
# This code is contributed by mohit kumar 29


C#

// C# program to find a number in minimum steps
using System;
using System.Collections.Generic;
public
class GFG
{
static readonly int InF = 99999;
// To represent data of a node in tree
public
class number
{
public
int no;
public
int level;
public
number() {}
public
number( int n, int l)
{
this .no = n;
this .level = l;
}
};
// Prints level of node n
static void findnthnumber( int n)
{
// Create a queue and insert root
Queue<number> q = new Queue<number>();
number r = new number(0, 1);
q.Enqueue(r);
// Do level order traversal
while (q.Count != 0)
{
// Remove a node from queue
number temp = q.Peek();
q.Dequeue();
// To astatic void infinite loop
if (temp.no >= InF || temp.no <= -InF)
break ;
// Check if dequeued number is same as n
if (temp.no == n)
{
Console.Write( "Found number n at level "
+ (temp.level - 1));
break ;
}
// Insert children of dequeued node to queue
q.Enqueue( new number(temp.no + temp.level, temp.level + 1));
q.Enqueue( new number(temp.no - temp.level, temp.level + 1));
}
}
// Driver code
public static void Main(String[] args)
{
findnthnumber(13);
}
}
// This code is contributed by gauravrajput1


Javascript

<script>
// JavaScript program to find a number in minimum steps
var InF = 99999;
// To represent data of a node in tree
class number
{
constructor(n, l)
{
this .no = n;
this .level = l;
}
};
// Prints level of node n
function findnthnumber(n)
{
// Create a queue and insert root
var q = [];
var r = new number(0, 1);
q.push(r);
// Do level order traversal
while (q.length != 0)
{
// Remove a node from queue
var temp = q[0];
q.shift();
// To astatic void infinite loop
if (temp.no >= InF || temp.no <= -InF)
break ;
// Check if dequeued number is same as n
if (temp.no == n)
{
document.write( "Found number n at level "
+ (temp.level - 1));
break ;
}
// Insert children of dequeued node to queue
q.push( new number(temp.no + temp.level, temp.level + 1));
q.push( new number(temp.no - temp.level, temp.level + 1));
}
}
// Driver code
findnthnumber(13);
</script>


输出:

Found number n at level 5

上述解决方案由 穆文 .

方法2:使用 矢量

上述解决方案对第n个时间实例使用二叉树,即-n和n。但随着树级别的增加,这将变得效率低下。对于abs(200)或以上的值,程序会给出分段错误。 下面的解决方案不会生成树,其复杂度等于所需的确切步骤数。此外,所需的步骤打印在数组中,该数组等于所需的精确总和。

主要思想:

  • +n和-n之间的距离是2*n。所以,如果你从+ve到-ve求反一个数字,它将产生2*n的差值,与之前的总和不同。
  • 如果一个数字在任意n的n(n+1)/2和(n+1)(n+2)/2之间,那么我们进入步骤(n+1)(n+2)/2,并尝试使用上面讨论的想法将总和减少到差值。
  • 如果我们转到n(n+1)/2,然后尝试增加,它最终将引导您达到相同的步数。 由于不能从n(n+1)/2中求反任何数(因为求和已经小于所需的求和),这证明了它需要最少的步数。

C++

// C++ program to Find a
// number in minimum steps
#include <bits/stdc++.h>
using namespace std;
vector< int > find( int n)
{
// Steps sequence
vector< int > ans;
// Current sum
int sum = 0;
int i;
// Sign of the number
int sign = (n >= 0 ? 1 : -1);
n = abs (n);
// Basic steps required to get
// sum >= required value.
for (i = 1; sum < n; i++) {
ans.push_back(sign * i);
sum += i;
}
// If we have reached ahead to destination.
if (sum > sign * n) {
/*If the last step was an odd number,
then it has following mechanism for
negating a particular number and
decreasing the sum to required number
Also note that it may require
1 more step in order to reach the sum. */
if (i % 2) {
sum -= n;
if (sum % 2) {
ans.push_back(sign * i);
sum += i++;
}
ans[(sum / 2) - 1] *= -1;
}
else {
/* If the current time instance is even
and sum is odd than it takes
2 more steps and few
negations in previous elements
to reach there. */
sum -= n;
if (sum % 2) {
sum--;
ans.push_back(sign * i);
ans.push_back(sign * -1 * (i + 1));
}
ans[(sum / 2) - 1] *= -1;
}
}
return ans;
}
// Driver Program
int main()
{
int n = 20;
if (n == 0)
cout << "Minimum number of Steps: 0Step sequence:0" ;
else {
vector< int > a = find(n);
cout << "Minimum number of Steps: " << a.size() << "Step sequence:" ;
for ( int i : a)
cout << i << " " ;
}
return 0;
}


JAVA

// Java program to Find a
// number in minimum steps
import java.util.*;
class GFG
{
static Vector<Integer> find( int n)
{
// Steps sequence
Vector<Integer> ans = new Vector<>();
// Current sum
int sum = 0 ;
int i = 1 ;
// Sign of the number
int sign = (n >= 0 ? 1 : - 1 );
n = Math.abs(n);
// Basic steps required to get
// sum >= required value.
for (; sum < n;)
{
ans.add(sign * i);
sum += i;
i++;
}
// If we have reached ahead to destination.
if (sum > sign * n)
{
/*If the last step was an odd number,
then it has following mechanism for
negating a particular number and
decreasing the sum to required number
Also note that it may require
1 more step in order to reach the sum. */
if (i % 2 != 0 )
{
sum -= n;
if (sum % 2 != 0 )
{
ans.add(sign * i);
sum += i;
i++;
}
int a = ans.get((sum / 2 ) - 1 );
ans.remove((sum / 2 ) - 1 );
ans.add(((sum / 2 ) - 1 ), a*(- 1 ));
}
else
{
/* If the current time instance is even
and sum is odd than it takes
2 more steps and few
negations in previous elements
to reach there. */
sum -= n;
if (sum % 2 != 0 )
{
sum--;
ans.add(sign * i);
ans.add(sign * - 1 * (i + 1 ));
}
ans.add((sum / 2 ) - 1 , ans.get((sum / 2 ) - 1 ) * - 1 );
}
}
return ans;
}
// Driver Program
public static void main(String[] args)
{
int n = 20 ;
if (n == 0 )
System.out.print( "Minimum number of Steps: 0Step sequence:0" );
else
{
Vector<Integer> a = find(n);
System.out.print( "Minimum number of Steps: " +
a.size()+ "Step sequence:" );
for ( int i : a)
System.out.print(i + " " );
}
}
}
// This code is contributed by aashish1995


Python3

# Python3 program to Find a
# number in minimum steps
def find(n):
# Steps sequence
ans = []
# Current sum
Sum = 0
i = 0
# Sign of the number
sign = 0
if (n > = 0 ):
sign = 1
else :
sign = - 1
n = abs (n)
i = 1
# Basic steps required to get
# sum >= required value.
while ( Sum < n):
ans.append(sign * i)
Sum + = i
i + = 1
# If we have reached ahead to destination.
if ( Sum > sign * n):
# If the last step was an odd number,
# then it has following mechanism for
# negating a particular number and
# decreasing the sum to required number
# Also note that it may require
# 1 more step in order to reach the sum.
if (i % 2 ! = 0 ):
Sum - = n
if ( Sum % 2 ! = 0 ):
ans.append(sign * i)
Sum + = i
i + = 1
ans[ int ( Sum / 2 ) - 1 ] * = - 1
else :
# If the current time instance is even
# and sum is odd than it takes
# 2 more steps and few
# negations in previous elements
# to reach there.
Sum - = n
if ( Sum % 2 ! = 0 ):
Sum - = 1
ans.append(sign * i)
ans.append(sign * - 1 * (i + 1 ))
ans[ int (( sum / 2 )) - 1 ] * = - 1
return ans
# Driver code
n = 20
if (n = = 0 ):
print ( "Minimum number of Steps: 0Step sequence:0" )
else :
a = find(n)
print ( "Minimum number of Steps:" , len (a))
print ( "Step sequence:" )
print ( * a, sep = " " )
# This code is contributed by rag2127


C#

// C# program to Find a
// number in minimum steps
using System;
using System.Collections.Generic;
public class GFG
{
static List< int > find( int n)
{
// Steps sequence
List< int > ans = new List< int >();
// Current sum
int sum = 0;
int i = 1;
// Sign of the number
int sign = (n >= 0 ? 1 : -1);
n = Math.Abs(n);
// Basic steps required to get
// sum >= required value.
for (; sum < n;)
{
ans.Add(sign * i);
sum += i;
i++;
}
// If we have reached ahead to destination.
if (sum > sign * n)
{
/*If the last step was an odd number,
then it has following mechanism for
negating a particular number and
decreasing the sum to required number
Also note that it may require
1 more step in order to reach the sum. */
if (i % 2 != 0)
{
sum -= n;
if (sum % 2 != 0)
{
ans.Add(sign * i);
sum += i;
i++;
}
int a = ans[((sum / 2) - 1)];
ans.RemoveAt((sum / 2) - 1);
ans.Insert(((sum / 2) - 1), a*(-1));
}
else
{
/* If the current time instance is even
and sum is odd than it takes
2 more steps and few
negations in previous elements
to reach there. */
sum -= n;
if (sum % 2 != 0)
{
sum--;
ans.Add(sign * i);
ans.Add(sign * -1 * (i + 1));
}
ans.Insert((sum / 2) - 1, ans[(sum / 2) - 1] * -1);
}
}
return ans;
}
// Driver Program
public static void Main(String[] args)
{
int n = 20;
if (n == 0)
Console.Write( "Minimum number of Steps: 0Step sequence:0" );
else
{
List< int > a = find(n);
Console.Write( "Minimum number of Steps: " +
a.Count+ "Step sequence:" );
foreach ( int i in a)
Console.Write(i + " " );
}
}
}
// This code is contributed by Rajput-Ji


Javascript

<script>
// JavaScript program to Find a
// number in minimum steps
function find(n)
{
// Steps sequence
let ans = [];
// Current sum
let sum = 0;
let i = 1;
// Sign of the number
let sign = (n >= 0 ? 1 : -1);
n = Math.abs(n);
// Basic steps required to get
// sum >= required value.
for (; sum < n;)
{
ans.push(sign * i);
sum += i;
i++;
}
// If we have reached ahead to destination.
if (sum > sign * n)
{
/*If the last step was an odd number,
then it has following mechanism for
negating a particular number and
decreasing the sum to required number
Also note that it may require
1 more step in order to reach the sum. */
if (i % 2 != 0)
{
sum -= n;
if (sum % 2 != 0)
{
ans.push(sign * i);
sum += i;
i++;
}
ans[parseInt(sum / 2, 10) - 1] =
ans[parseInt(sum / 2, 10) - 1]*(-1);
}
else
{
/* If the current time instance is even
and sum is odd than it takes
2 more steps and few
negations in previous elements
to reach there. */
sum -= n;
if (sum % 2 != 0)
{
sum--;
ans.push(sign * i);
ans.push(sign * -1 * (i + 1));
}
ans[parseInt(sum / 2, 10) - 1] =
ans[parseInt(sum / 2, 10) - 1] * -1;
}
}
return ans;
}
let n = 20;
if (n == 0)
document.write( "Minimum number of Steps: 0" +
"</br>" + "Step sequence:" + "</br>" + "0" );
else
{
let a = find(n);
document.write( "Minimum number of Steps: " +
a.length + "</br>" + "Step sequence:" +
"</br>" );
for (let i = 0; i < a.length; i++)
document.write(a[i] + " " );
}
</script>


输出:

 Minimum number of Steps: 7Step sequence:1 2 3 -4 5 6 7

如果n是所需的总和,s是最小步数,则: n=(s+1)*(s+2)/2+1(或+2) 因此n=O(s*s) 因此s=O(sqrt(n)) 空间复杂度:O(sqrt(n)) 时间复杂度:O(sqrt(n)) https://youtu.be/GcrapHAFnLg 如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。

© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享