我正在研究一个问题,并花了一些时间。 问题陈述: 给出一组正负整数。如果索引处的数字n为正,则向前移动n步。相反,如果它是负数(-n),则向后移动n步。假设数组的第一个元素在最后一个元素的前面,而最后一个元素在第一个元素的后面。确定此数组中是否存在循环。循环以特定索引开始和结束,循环中包含多于1个元素。循环必须是"前进"或者"向后'。
示例1:给定数组[2,-1,1,2,2],存在来自索引0的循环 - > 2 - > 3 - > 0
示例2:给定数组[-1,2],没有循环。
注意:给定数组保证不包含元素" 0"。
你能在O(n)时间复杂度和O(1)空间复杂度下做到吗?
这是我正在进行的解决方案,但是,当我没有检测到循环时,我不知道如何结束do-while条件。我相信如果没有检测到循环,我的代码将无限运行。
public static boolean circularArrayLoop(int[] nums) {
int size = nums.length;
if(size < 2) return false;
int loopStart = nums[0];
int index = 0;
int start = nums[0];
do{
if(nums[index] > 0){
index = moveForward(index, nums[index], size);
}else {
index = moveBackward(index, Math.abs(nums[index]), size);
}
}while (loopStart != nums[index]);
}
答案 0 :(得分:0)
我认为不能保证循环将继续使用第一个元素,这是错误的吗?因此,您不能只做int loopStart = nums[0];
[2, -1, 1, 4, 2]
,那么循环将来自索引0 -> 2 -> 3 -> 2
。而且,使用loopstart进行检查是行不通的,因为它会检查sums[0]
。 一个好的解决方案是使用2个变量并以不同的速度移动它们(速度的两倍)。如果数组/链表是循环的,那么你将到达var1等于var2的点。
这是伪代码:
if array.length<=1
return false
int i=0;
//loop is when "var1 == var2"
//end is when "var1 == abs(array.length)"
loop (until var1 == var2 or var1 reaches the end)
var1 = moveToNext(var1)
if (i++ % 2 == 0)
var2 = moveToNext(var2)
return var1 == var2;
这与使用链接列表的一般问题非常相似:How to detect a loop in a linked list?
答案 1 :(得分:0)
由于保证没有值为0的元素,因此总会有一个循环。限定符是循环必须大于单个元素的长度。
在这种情况下,当按照数组元素值的指示前进到下一个索引时,会导致达到相同的索引,&#34; no&#34;循环存在。
快速和慢速移动游标可用于查找循环的开始。然后推进单个游标直到它返回到相同的索引将允许您迭代循环的元素。如果单个进程将光标返回到相同的索引,则不存在循环。
public static void main(String[] args) {
int[] loop = {2, -1, 1, 2, 2};
int[] noloop = {-1, 2};
System.out.println(circularArrayLoop(loop));
System.out.println(circularArrayLoop(noloop));
}
static int nextIndex(int[] nums, int cur) {
// Get next index based on value taking into account wrapping around
}
static boolean circularArrayLoop(int[] nums) {
int fast = 0;
int slow = 0;
do {
// advance fast cursor twice
// advance slow cursor once
} while (fast != slow);
int next = nextIndex(nums, fast);
// return if the loop has more than a single element
}
答案 2 :(得分:0)
这可以看作是定向(可能是断开连接的)图形中的循环检测版本,或者更像是在给定图形中找到所有连接子图的最小生成树。数组中的数字是顶点,并且将基于顶点值在顶点之间形成边。没有已知的图解析算法可以在O(1)空间复杂度中解决它。这可能在O(n)时间复杂度中得到解决,因为在这种情况下,最佳图解析算法可以在O(V + E)时间和V = E中求解,这使得可以在一些情况下解决O(n)时间复杂度。案例。最着名的算法是Kruskal:http://www.geeksforgeeks.org/greedy-algorithms-set-2-kruskals-minimum-spanning-tree-mst/,它在O(nlogn)时间内得到解决。