Java 在数组中查找和最小的两个非后续元素
简介:据我所知,这个问题还没有被问到。Java 在数组中查找和最小的两个非后续元素,java,arrays,algorithm,time-complexity,minimum,Java,Arrays,Algorithm,Time Complexity,Minimum,简介:据我所知,这个问题还没有被问到。 这是一个面试问题。 我甚至没有特别寻找代码解决方案,任何算法/伪代码都可以 问题:给定一个整数数组int[]A及其大小N,找到2个非后续的(不能在数组中相邻)元素的最小和。此外,答案不得包含第一个或最后一个元素(索引0和n-1)。此外,解决方案应为O(n)时间和空间复杂性 例如,当A=[5,2,4,6,3,7]时,答案是5,因为2+3=5 当A=[1,2,3,3,2,1]时,答案是4,因为2+2=4,并且您不能选择1中的任何一个,因为它们位于数组的末端
这是一个面试问题。
我甚至没有特别寻找代码解决方案,任何算法/伪代码都可以
问题:给定一个整数数组
int[]A
及其大小N
,找到2个非后续的(不能在数组中相邻)元素的最小和。此外,答案不得包含第一个或最后一个元素(索引0
和n-1
)。此外,解决方案应为O(n)
时间和空间复杂性
例如,当A=[5,2,4,6,3,7]
时,答案是5
,因为2+3=5
当
A=[1,2,3,3,2,1]
时,答案是4
,因为2+2=4
,并且您不能选择1
中的任何一个,因为它们位于数组的末端
尝试:起初,我认为解决方案中的一个数字必须是数组中最小的一个(除了第一个和最后一个),但反例很快反驳了这一点
A=[4,2,1,2,4]
->4(2+2)
然后我想如果我在数组中找到2最小的数字(除了第一个和最后一个),那么解决方案就是这两个。这显然很快就失败了,因为我不能选择两个相邻的数字,如果我必须选择非相邻的数字,那么这就是问题的定义:)
最后我想,好吧,我将在数组中找到3最小的数字(除了第一个和最后一个),解决方案必须是其中的两个,因为其中的两个必须不相邻。
由于A=[2,2,1,2,4,2,6]
->2+1=3
,这个也失败了,因为我会找到2,1,2
,但假设我在索引1,2,3
中找到2,1,2
,这不一定会起作用(如果我在索引5
中特别找到2
,我会这样做,但不幸的是,我不能保证这一点)
问题:
现在我被难住了,有人能想出一个可行的解决方案/想法吗?编辑:没错,我完全忽略了邻接约束。 幸运的是,我想到了一个解决办法。 算法如下所示:
public class Main {
int solve(int[] array) {
int answer = Integer.MAX_VALUE;
int min = array[1];
for (int i = 3; i < array.length - 1; i++) {
min = Math.min(min, array[i - 2]);
if (array[i] + min < answer) {
answer = array[i] + min;
}
}
return answer;
}
}
(O(n))
(O(n))
O(1)
-只是索引检查)O(n)
)找到四个最小值,考虑四个之间的所有可能性。最小的不相邻于最小的第二个、第三个或最小第四个;另一个可能更好的是第二个和最小的第三个(假设它们是不相邻的)。(或者更准确地说是它们的索引)(
k
足够大,比如说10
)。可以肯定的是,想要的一对在它们之间。现在您只需检查可能的50
对,并选择满足约束的最佳对
您不需要10
,只需要更少,但需要更多3
:)
编辑:查找k
最小的数字是O(n)
,因为您只需在堆中保留最好的10
(添加新元素,删除最大O(k*logk)=O(1)
操作)
然后将有一对满足约束条件(彼此不相邻)。同样清楚的是,如果使用不是从k
元素中选择的元素构建总和,那么它将大于从k
元素中选择的最佳对
最多检查
k*k
对也是O(1)
,因此整个运行时间是O(n)
我认为这应该是可行的:
找到最小的3个元素及其索引。因为它们不能都是相邻的,所以从中选择2个
如果它们都是相邻的,最小数在中间,则遍历所有元素,找到第四个最小元素,选择最小值<代码> MI1+MI4,<代码> MIN2+MI3,无论哪个较小。 您也可以在一次迭代中完成此操作。
算法:public static int minSumNonAdjNonEnd(int[] array)
{
// 1. Find minimum
int minIdx1 = -1;
int minValue1 = Integer.MAX_VALUE;
for (int i = 1; i < array.length - 1; i++)
{
if (array[i] < minValue1)
{
minIdx1 = i;
minValue1 = array[i];
}
}
// 2. Find minimum not among (1) or adjacents.
int minIdx2 = -1;
int minValue2 = Integer.MAX_VALUE;
for (int i = 1; i < array.length - 1; i++)
{
if ((i < minIdx1 - 1 || i > minIdx1 + 1) && (array[i] < minValue2))
{
minIdx2 = i;
minValue2 = array[i];
}
}
boolean sum1Exists = (minIdx1 > -1 && minIdx2 > -1);
int sum1 = minValue1 + minValue2;
// 3. Find minimum not among (1).
int minIdx3 = -1;
int minValue3 = Integer.MAX_VALUE;
for (int i = 1; i < array.length - 1; i++)
{
if ((i != minIdx1) && (array[i] < minValue3))
{
minIdx3 = i;
minValue3 = array[i];
}
}
// 4. Find minimum not among(3) or adjacents.
int minIdx4 = -1;
int minValue4 = Integer.MAX_VALUE;
for (int i = 1; i < array.length - 1; i++)
{
if ((i < minIdx3 - 1 || i > minIdx3 + 1) && (array[i] < minValue4))
{
minIdx4 = i;
minValue4 = array[i];
}
}
boolean sum2Exists = (minIdx3 > -1 && minIdx4 > -1);
int sum2 = minValue3 + minValue4;
if (sum1Exists)
{
if (sum2Exists)
return Math.min(sum1, sum2);
else
return sum1;
}
else
{
if (sum2Exists)
return sum2;
else
throw new IllegalArgumentException("impossible");
}
}
以下是一个算法的实时javascript实现:
- 查找4个最小的元素(不包括搜索中的第一个/最后一个元素)
- 查找在原始数组中不相邻的这4个元素对
- 从这些对中查找具有最小和的对
函数findMinNoNajacentPair(a){
var mins=[];
//快速出口:
if(a.length<5)返回{error:“没有解决方案,元素太少。”};
if(a.some(isNaN))返回{error:“给定的非数值。”};
//按索引收集4个最小值
对于(var i=1;istatic void printMinimalSum(int[] A) {
// Looking for mins so we init this with max value
int[] mins = new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE};
// Indices, used just to print the solution
int[] indices = new int[]{-1, -1, -1};
// If the array has length 5 then there's only one solution with the 2nd and 4th elements
if (A.length == 5) {
mins[0] = A[1];
indices[0] = 1;
mins[1] = A[3];
indices[1] = 3;
} else {
// Loop on the array without considering the first and the last element
for (int i = 1; i < A.length - 1; i++) {
// We consider each element which is smaller than its neighbours
if ((i == 1 && A[i] < A[i + 1]) // 1: first element, compare it with the second one
|| (i == A.length - 2 && A[i] < A[i - 1]) // 2: last element, compare it with the previous one
|| (A[i] < A[i + 1] && A[i] < A[i - 1])) { // 3: mid element, compare it with both neighbors
// If the element is "legal" then we see if it's smaller than the 3 already saved
if (A[i] < mins[0]) {
mins[0] = A[i];
indices[0] = i;
} else if (A[i] < mins[1]) {
mins[1] = A[i];
indices[1] = i;
} else if (A[i] < mins[2]) {
mins[2] = A[i];
indices[2] = i;
}
}
}
}
// Compute the 3 sums between those 3 elements
int[] sums = new int[]{Math.abs(mins[0]+mins[1]), Math.abs(mins[0]+mins[2]), Math.abs(mins[1]+mins[2])};
// Find the smaller sum and print it
if (sums[0] < sums[1] || sums[0] < sums[2]){
System.out.println("Sum = " + sums[0] + " (elements = {" + mins[0] + "," + mins[1] + "}, indices = {" + indices[0] + "," + indices[1] + "}");
} else if (sums[1] < sums[0] || sums[1] < sums[2]){
System.out.println("Sum = " + sums[1] + " (elements = {" + mins[0] + "," + mins[2] + "}, indices = {" + indices[0] + "," + indices[2] + "}");
} else {
System.out.println("Sum = " + sums[2] + " (elements = {" + mins[1] + "," + mins[2] + "}, indices = {" + indices[1] + "," + indices[2] + "}");
}
}
public static void main(String[] args) {
printMinimalSum(new int[]{5, 2, 4, 6, 3, 7});
printMinimalSum(new int[]{1, 2, 3, 3, 2, 1});
printMinimalSum(new int[]{4, 2, 1, 2, 4});
printMinimalSum(new int[]{2, 2, 1, 2, 4, 2, 6});
}
Sum = 5 (elements = {2,3}, indices = {1,4}
Sum = 4 (elements = {2,2}, indices = {1,4}
Sum = 4 (elements = {2,2}, indices = {1,3}
Sum = 3 (elements = {1,2}, indices = {2,5}
public static int[] minimumSumOfNonAcjacentElements(int[] a) {
// the result for the sequence a[1:i]
int minSum = Integer.MAX_VALUE;
int minSumElement1 = Integer.MAX_VALUE;
int minSumElement2 = Integer.MAX_VALUE;
// the minimum element eligible for joining with a[i], i.e. from a[1 : i-2]
int minElement = a[1];
int prevElement = a[2]; // a[i - 1]
for (int i = 3; i + 1 < a.length; i++) {
int sum = minElement + a[i];
if (sum < minSum) {
minSum = sum;
minSumElement1 = minElement;
minSumElement2 = a[i];
}
if (prevElement < minElement) {
minElement = prevElement;
}
prevElement = a[i];
}
return new int[] {minSumElement1, minSumElement2};
}
private static void test(int minSumIndex1, int minSumIndex2, int... input) {
int[] result = minimumSumOfNonAcjacentElements(input);
if (result[0] == minSumIndex1 && result[1] == minSumIndex2) {
// ok
} else {
throw new AssertionError("Expected: " + minSumIndex1 + ", " + minSumIndex2 + ". Actual=" + Arrays.toString(result));
}
}
public static void main(String[] args) throws Exception {
test(2, 2, 4, 2, 1, 2, 4);
test(1, 2, 2, 2, 1, 2, 4, 2, 6);
test(1, 2, 0, 2, 1, 2, 4, 2, 0);
System.out.println("All tests passed.");
}
DP[i] = min(DP[i-1], min(first_data, second_data))
import random
def get_min(numbers):
#disregard the first and last element
numbers = numbers[1:len(numbers)-1]
#for remembering the past results
DP = [0]*len(numbers)
#for keeping track of minimum till now found
table = [0]*len(numbers)
high_number = 1 << 30
min_number = numbers[0]
table[0] = min_number
for i in range(0, len(numbers)):
DP[i] = high_number
for i in range(1, len(numbers)):
if numbers[i] < min_number:
min_number = numbers[i]
table[i] = numbers[i]
else:
table[i] = min_number
for i in range(0, len(numbers)):
min_first, min_second = high_number, high_number
if i >= 2:
min_first = numbers[i] + table[i-2]
if i >= 3:
min_second = numbers[i-1] + table[i-3]
if i >= 1:
DP[i] = min(min(DP[i-1], min_first), min_second)
return DP[len(numbers)-1]
input = random.sample(range(100), 10)
print(input)
print(get_min(input))
public class Main {
int solve(int[] array) {
int answer = Integer.MAX_VALUE;
for (int i = 3; i < array.length - 1; i++) {
for (int j = 1; j < i - 1; j++) {
if (array[i] + array[j] < answer) {
answer = array[i] + array[j];
}
}
}
return answer;
}
}
public class Main {
int solve(int[] array) {
int answer = Integer.MAX_VALUE;
int min = array[1];
for (int i = 3; i < array.length - 1; i++) {
min = Math.min(min, array[i - 2]);
if (array[i] + min < answer) {
answer = array[i] + min;
}
}
return answer;
}
}
int minSum(int[] A){
int minSum=Integer.MAX_VALUE;
int min= Integer.MAX_VALUE;
for(int i=3; i<A.length-1; i++){
min= Math.min(A[i-2], min);
minSum = Math.min(min+A[i], minSum);
}
return minSum;
}