我被问到这个面试问题,我完全懵了。各位大佬怎么解决的:
从数组的开头到结尾,以最小化您登陆的元素总和的方式。
- 您可以移动到下一个元素,即从索引 1 转到索引 2。
- 或者你可以跳过一个元素。即从索引 1 到索引 3。
我被问到这个面试问题,我完全懵了。各位大佬怎么解决的:
从数组的开头到结尾,以最小化您登陆的元素总和的方式。
假设你只从左到右移动,并且你想找到一种方法从一个元素数组的索引0
到索引,这样你走的路径的总和是最小的。从 index ,您只能前进到 index或 index 。n - 1
n
i
i + 1
i + 2
观察从 index 到 index 的最小路径是从 index 到 index 的最小路径与从 index0
到 index的最小k
路径之间的最小值。根本没有其他途径可走。0
k - 1
0
k- 2
因此,我们可以有一个动态规划的解决方案:
DP[0] = A[0]
DP[1] = A[0] + A[1]
DP[k] = min(DP[0], DP[1]) + A[k]
A
是元素的数组。数组将存储从 index
DP
到达 index 处元素的最小总和。i
0
结果将在DP[n - 1]
.
这似乎是动态编程解决方案的理想场所。
跟踪两个值,奇数/偶数。
我们将Even
表示我们使用了以前的值,并Odd
表示我们没有。
int Even = 0; int Odd = 0;
int length = arr.length;
从后面开始。我们可以取或不取号码。所以:
Even = arr[length];
Odd = 0;`
现在我们用两个案例移动到下一个元素。要么我们是偶数,在这种情况下,我们可以选择获取元素或跳过它。或者我们很奇怪,不得不接受这个元素。
int current = arr[length - 1]
Even = Min(Even + current, Odd + current);
Odd = Even;
我们可以对此进行循环并实现 O(n) 解决方案!
爪哇:
static int getMinSum(int elements[])
{
if (elements == null || elements.length == 0)
{
throw new IllegalArgumentException("No elements");
}
if (elements.length == 1)
{
return elements[0];
}
int minSum[] = new int[elements.length];
minSum[0] = elements[0];
minSum[1] = elements[0] + elements[1];
for (int i = 2; i < elements.length; i++)
{
minSum[i] = Math.min(minSum[i - 1] + elements[i], minSum[i - 2] + elements[i]);
}
return Math.min(minSum[elements.length - 2], minSum[elements.length - 1]);
}
输入:
int elements[] = { 1, -2, 3 };
System.out.println(getMinSum(elements));
输出:
-1
案例描述:
我们从索引 0 开始。我们必须取 1。现在我们可以去索引 1 或 2。因为 -2 很有吸引力,所以我们选择它。现在我们可以去索引 2 或跳它。更好的跳跃,我们的和是最小的 1 + (-2) = -1。
另一个例子(伪代码):
getMinSum({1, 1, 10, 1}) == 3
getMinSum({1, 1, 10, 100, 1000}) == 102
算法:
O(n) 复杂度。动态规划。我们从左到右填充 minSum 数组。不变量:minSum[i] = min(minSum[i - 1] + elements[i] /* move by 1 */ , minSum[i - 2] + elements[i] /* hop */ )
.