以最少的步骤找到一个数字
给定从 -INFINITY 到 +INFINITY 的无限数线,我们为零。我们可以在每第 n 次左右移动 n 步。
方法 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 = 10
Output : 4
We can reach 10 in 4 steps, 1, 3, 6, 10
Input : n = 13
Output : 5
We can reach 10 in 4 steps, -1, 2, 5, 9, 14
这个问题可以建模为树。我们将初始点 0 放在 root 处,将 1 和 -1 作为 root 的孩子。下一级包含距离 2 处的值,依此类推。
0
/ \
-1 1
/ \ / \
1 -3 -1 3
/ \ / \ / \ / \
现在的问题是找到值 n 的关闭节点到根。这个想法是对树进行级别顺序遍历以找到最近的节点。请注意,对最近的节点使用 DFS 绝不是一个好主意(我们最终可能会降低许多不必要的级别)。
下面是上述想法的 C++、 Python实现。
C++
// C++ program to find a number in minimum steps
#include
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 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 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 q = new Queue();
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
C++
// C++ program to Find a
// number in minimum steps
#include
using namespace std;
vector find(int n)
{
// Steps sequence
vector 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: 0\nStep sequence:\n0";
else {
vector a = find(n);
cout << "Minimum number of Steps: " << a.size() << "\nStep sequence:\n";
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 find(int n)
{
// Steps sequence
Vector 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: 0\nStep sequence:\n0");
else
{
Vector a = find(n);
System.out.print("Minimum number of Steps: " +
a.size()+ "\nStep sequence:\n");
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: 0\nStep sequence:\n0")
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 find(int n)
{
// Steps sequence
List ans = new List();
// 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: 0\nStep sequence:\n0");
else
{
List a = find(n);
Console.Write("Minimum number of Steps: " +
a.Count+ "\nStep sequence:\n");
foreach (int i in a)
Console.Write(i + " ");
}
}
}
// This code is contributed by Rajput-Ji
Javascript
输出:
Found number n at level 5
以上解决方案由Mu Ven提供。
方法 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
using namespace std;
vector find(int n)
{
// Steps sequence
vector 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: 0\nStep sequence:\n0";
else {
vector a = find(n);
cout << "Minimum number of Steps: " << a.size() << "\nStep sequence:\n";
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 find(int n)
{
// Steps sequence
Vector 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: 0\nStep sequence:\n0");
else
{
Vector a = find(n);
System.out.print("Minimum number of Steps: " +
a.size()+ "\nStep sequence:\n");
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: 0\nStep sequence:\n0")
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 find(int n)
{
// Steps sequence
List ans = new List();
// 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: 0\nStep sequence:\n0");
else
{
List a = find(n);
Console.Write("Minimum number of Steps: " +
a.Count+ "\nStep sequence:\n");
foreach (int i in a)
Console.Write(i + " ");
}
}
}
// This code is contributed by Rajput-Ji
Javascript
输出 :
Minimum number of Steps: 7
Step sequence:
1 2 3 -4 5 6 7