我尝试使用递归方法检查整数数组中的最后一个数字(总是0)(所有> 0整数)是否可通过增加(或减少)数组的索引来访问当前索引的数组元素的值,同时保持在数组的范围内。
示例:
说我们有以下数组,并且起始索引== 0:
int[] arr = {3, 6, 4, 1, 3, 4, 2, 5, 3, 0};
步骤0:index = 0,value = 3
步骤1:index = 3,value = 1
第2步:index = 4,value = 3
步骤3:index = 7,value = 5
步骤4:index = 2,value = 4
步骤5:index = 6,value = 2
步骤6:index = 8,value = 3
步骤7:index = 5,value = 4
步骤8:index = 9,value = 0 - end
我目前的代码:
static bool Solveable(int index, int[] arr)
{
if (arr[index] == 0)
return true;
if (index + arr[index] < arr.Length)
return Solveable(index + arr[index], arr);
if (index - arr[index] >= 0)
return Solveable(index - arr[index], arr);
return false;
}
这个问题是它只适用于可解决的情况,所有其他情况都会导致stackoverflow异常。
如何在不使用全局变量存储以前的结果的情况下解决这个问题?
编辑:
我只能使用参数:(int index,int [] arr)
答案 0 :(得分:2)
对于无法解决的情况,你的堆栈溢出是正确的:递归代码的行为就像一只狗追逐它自己的尾巴,直到它达到堆栈限制。
幸运的是,你可以通过观察你最多有N
个步骤到达数组的末尾来打破这种无限递归,如果你要达到它的话。因此,您可以添加第三个参数来指示您已经采取了多少步骤。如果在步数通过N
之前达到零,则您有一条路径;否则,你没有路径。
static bool Solveable(int index, int[] arr, int stepsSoFar) {
if (arr[index] == 0)
return true;
if (stepsSoFar > arr.Length)
return false;
...
// The rest of your code; pass stepsSoFar+1 down to the next level
}
我只能使用我的代码段中包含的两个参数
您可以通过将arr
放入-1
来标记您在arr
内访问过的索引。为了保留数组的原始状态,将旧值存储在局部变量中,并在返回之前将其重新设置为static bool Solveable(int index, int[] arr) {
if (arr[index] == 0)
return true;
if (arr[index] == -1)
return false;
int oldArrAtIndex = arr[index];
arr[index] = -1;
try {
...
// The rest of your code
} finally {
arr[index] = oldArrAtIndex;
}
}
:
@WebListener
public class MainWebListener implements ServletContextListener {
private Thread threadQueueListener;
private QueueThreadListener queueListener;
@Override
public void contextDestroyed(ServletContextEvent arg0) {
try {
queueListener.disconnectQueue();
Thread.sleep(QueueThreadListener.QUEUE_DELIVERY_TIMEOUT + 20);
} catch (Throwable tt) {
tt.printStackTrace();
}
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
try {
queueListener = new QueueThreadListener();
threadQueueListener = new Thread(queueListener);
threadQueueListener.setContextClassLoader(Thread.currentThread().getContextClassLoader());
threadQueueListener.start();
} catch (Throwable tt) {
tt.printStackTrace();
}
}
}
答案 1 :(得分:1)
传递跟踪您已经旅行过的指数的第三个参数。如果您已经尝试过当前索引,请停止处理。
此外,您可能希望更改以适应任何方向的旅行:
var solvable = false;
//...
if (index + arr[index] < arr.Length)
solvable = Solveable(index + arr[index], arr);
if (!solvable && index - arr[index] >= 0)
solvable = Solveable(index - arr[index], arr);
return solvable;
答案 2 :(得分:1)
学校作业与否,关于递归的课程,没有增加复杂性。
<div id="nav">
<div id="wrap">
<ul>
<li><a href="home.html">Home</a></li><li>
<a href="#">Study</a>
<ul>
<li><a href="Present.html">Present Simple</a></li><li>
<a href="Possessives.html">Possesives</a></li><li>
<a href="Articles.html">Articles</a></li><li>
<a href="Modal.html">Modal Verbs</a></li><li>
<a href="Prepositions.html">Prepositions</a></li><li>
<a href="Plural.html">Plural of nouns</a></li><li>
<a href="Countability.html">Countability</a></li>
</ul>
</li><li>
<a href="#">Games</a>
<ul>
<li><a href="#">Riddles</a></li><li>
<a href="#">Flip card game</a></li><li>
<a href="#">Spot the mistake</a></li><li>
<a href="#">Multiple choice</a></li>
</ul>
</li><li>
<a href="oferta.html">Shop</a></li><li>
<a href="contact.html">Contact</a></li><li>
<a href="about.html">About Us</a></li>
<li style="float:right"><a><img src="gmail.png" height="30px" width="30px"></a></li> <li style="float:right"><a><img src="twitter.png" height="30px" width="30px"></a></li><li style="float:right"><a><img src="facebook.png" height="30px" width="30px"></a></li>
</ul>
</div>
</div>
答案 3 :(得分:0)
您可以传递一个包含当前访问过的索引的数组,而不是传递int索引,如果您的下一个索引包含在被访问数组中,那么您只需要中断并返回false。
高层次的代码理念是:
static void Main(string[] args)
{
int[] arr = { 3, 6, 4, 1, 3, 4, 2, 5, 3, 0 };
var result = Solveable(new[] {0}, arr);
Console.WriteLine(result);
Console.ReadLine();
}
static bool Solveable(int[] path, int[] arr)
{
var index = path.Last();
if (arr[index] == 0)
return true;
if (index + arr[index] < arr.Length)
{
var nextIndex = index + arr[index];
var nextStepPath = path.Concat(new[] { nextIndex }).ToArray();
if (path.Contains(nextIndex))
return false;
return Solveable(nextStepPath, arr);
}
if (index - arr[index] >= 0)
{
var nextIndex = index - arr[index];
var nextStepPath = path.Concat(new[] {nextIndex}).ToArray();
if (path.Contains(nextIndex))
return false;
return Solveable(nextStepPath, arr);
}
return false;
}
它需要一些清理,但为您提供高级的想法,并且只使用2个参数而不为您的数组引入类/结构。
答案 4 :(得分:0)
这是一种不修改状态的算法:
static bool Solveable(int index, int[] arr)
{
if (arr[index] == 0)
return true;
int nextIndex = index + arr[index];
if (nextIndex < arr.Length)
return Solveable(nextIndex, arr);
// Search for a previous index that leads to a different path
int prevIndex;
while (true)
{
prevIndex = index - arr[index];
if (prevIndex < 0)
return false; // Not found, we are done
if (prevIndex + arr[prevIndex] != index)
return Solveable(prevIndex, arr); // Process the other path
index = prevIndex; // Keep searching
}
}
关键部分是非递归后退步骤处理部分(参见代码中的注释)。