用最小的总和制作独特的数组

时间:2017-10-08 08:31:54

标签: algorithm data-structures

这是一个面试问题。给定一个数组,例如[3,2,1,2,7],我们希望通过递增重复元素使这个数组中的所有元素都是唯一的,并且我们要求精化数组的总和是最小的。例如[3,2,1,2,7]的答案是[3,2,1,4,7],其总和是17.任何想法?

4 个答案:

答案 0 :(得分:2)

这不像我之前的评论所说的那么简单,但它并不是非常复杂。

首先,对输入数组进行排序。如果能够恢复元素的原始顺序很重要,那么记录用于排序的排列。

其次,从左到右扫描排序的数组(即从低到高)。如果元素小于或等于其左边的元素,则将其设置为大于该元素的元素。

伪代码

  sar = sort(input_array)
  for index = 2:size(sar)   ! I count from 1
      if sar(index)<=sar(index-1) sar(index) = sar(index-1)+1
  forend

结果总和最小?我已经说服自己,这是通过一些头痛和试验,但我还没有得到正式的证据。

答案 1 :(得分:1)

如果你只需要找到一个最好的解决方案,这里有一些解释的algorythm。 这个问题的想法是找到一个最优的解决方案,只有通过测试所有现有的解决方案才能找到它(好吧,它们是无限的,让我们坚持合理的解决方案)。

我在C中编写了一个程序,因为我对它很熟悉,但你可以将它移植到你想要的任何语言中。

程序执行此操作:它尝试将一个值增加到可能的最大值(我将解释如何在代码部分的注释中找到它),而不是找不到解决方案,减少此值并继续与下一个等等。

这是一个指数的算法,因此对于重复数据的大值来说它会非常缓慢(但是,它确保找到最佳解决方案)。

我用你的例子测试了这段代码,它起作用了;不确定是否还有任何错误,但代码(在C中)就是这个。

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
typedef int BOOL;   //just to ease meanings of values
#define TRUE 1
#define FALSE 0

为了减轻理解,我做了一些typedef。别担心。

typedef struct duplicate {      //used to fasten the algorythm; it uses some more memory just to assure it's ok
    int value;
    BOOL duplicate;
} duplicate_t;

int maxInArrayExcept(int *array, int arraySize, int index); //find the max value in array except the value at the index given
                                                            //the result is the max value in the array, not counting th index
int *findDuplicateSum(int *array, int arraySize);
BOOL findDuplicateSum_R(duplicate_t *array, int arraySize, int *tempSolution, int *solution, int *totalSum, int currentSum);    //resursive function used to find solution
BOOL check(int *array, int arraySize);  //checks if there's any repeated value in the solution

这些是我们需要的所有功能。为了理解目的,所有人都分开了。 首先,我们有一个结构。此结构用于避免在每次迭代时检查给定索引上的值是否最初是重复的。我们不想修改任何最初没有重复的值。

然后,我们有几个函数:首先,我们需要看到最坏的情况:重复的值之后的每个值都已被占用:然后我们需要将重复值增加到达到的最大值+ 1。 然后,我们将在稍后讨论主要功能。 检查功能仅检查临时解决方案中是否存在重复值。

int main() {                            //testing purpose
    int i;
    int testArray[] = { 3,2,1,2,7 };    //test array
    int nTestArraySize = 5;             //test array size
    int *solutionArray;                 //needed if you want to use the solution later
    solutionArray = findDuplicateSum(testArray, nTestArraySize);
    for (i = 0; i < nTestArraySize; ++i) {
        printf("%d ", solutionArray[i]);
    }
    return 0;
}

这是主要功能:我用它来测试一切。

int * findDuplicateSum(int * array, int arraySize)
{
    int *solution = malloc(sizeof(int) * arraySize);
    int *tempSolution = malloc(sizeof(int) * arraySize);
    duplicate_t *duplicate = calloc(arraySize, sizeof(duplicate_t));
    int i, j, currentSum = 0, totalSum = INT_MAX;
    for (i = 0; i < arraySize; ++i) {
        tempSolution[i] = solution[i] = duplicate[i].value = array[i];
        currentSum += array[i];
        for (j = 0; j < i; ++j) {   //to find ALL the best solutions, we should also put the first found value as true; it's just a line more
                                //yet, it saves the algorythm half of the duplicated numbers (best/this case scenario)
            if (array[j] == duplicate[i].value) {
                duplicate[i].duplicate = TRUE;
            }
        }
    }
    if (findDuplicateSum_R(duplicate, arraySize, tempSolution, solution, &totalSum, currentSum));
    else {
        printf("No solution found\n");
    }
    free(tempSolution);
    free(duplicate);
    return solution;
}

这个函数做了很多事情:首先,它设置解决方案数组,然后初始化解决方案值和重复数组,即用于在启动时检查重复值的数组。然后,我们找到当前的总和,并将最大可用总和设置为可能的最大整数。 然后,调用递归函数;这个给了我们关于找到解决方案的信息(应该是Always),然后我们将解决方案作为数组返回。

int findDuplicateSum_R(duplicate_t * array, int arraySize, int * tempSolution, int * solution, int * totalSum, int currentSum)
{
    int i;
    if (check(tempSolution, arraySize)) {
        if (currentSum < *totalSum) {       //optimal solution checking
            for (i = 0; i < arraySize; ++i) {
                solution[i] = tempSolution[i];
            }
            *totalSum = currentSum;
        }
        return TRUE; //just to ensure a solution is found
    }
    for (i = 0; i < arraySize; ++i) {
        if (array[i].duplicate == TRUE) {
            if (array[i].duplicate <= maxInArrayExcept(solution, arraySize, i)) {   //worst case scenario, you need it to stop the recursion on that value
                tempSolution[i]++;
                return findDuplicateSum_R(array, arraySize, tempSolution, solution, totalSum, currentSum + 1);
                tempSolution[i]--;  //backtracking
            }
        }
    }
    return FALSE; //just in case the solution is not found, but we won't need it
}

这是递归函数。它首先检查解决方案是否正常,以及它是否是迄今为止发现的最佳解决方案。然后,如果一切正确,它会使用临时值更新实际解决方案,并更新最佳条件。 然后,我们迭代每个重复的值(如果排除其他索引),我们在递归中前进,直到(如果不幸)我们达到最坏的情况:检查条件不满足高于最大值。 然后我们必须回溯并继续迭代,这将继续其他值。

PS:这里可以进行优化,如果我们将最佳条件从检查移动到for:如果解决方案已经不是最优的,我们就不能期望找到更好的只是添加东西。

硬编码已经结束,并且有支持功能:

int maxInArrayExcept(int *array, int arraySize, int index) {
    int i, max = 0;
    for (i = 0; i < arraySize; ++i) {
        if (i != index) {
            if (array[i] > max) {
                max = array[i];
            }
        }
    }
    return max;
}

BOOL check(int *array, int arraySize) {
    int i, j;
    for (i = 0; i < arraySize; ++i) {
        for (j = 0; j < i; ++j) {
            if (array[i] == array[j]) return FALSE;
        }
    }
    return TRUE;
}

我希望这很有用。 如果有什么不清楚的话写。

答案 2 :(得分:0)

嗯,我在一次采访中得到了同样的问题。 不确定你是否还需要它。但这就是我做到的。它运作良好。

num_list1 = [2,8,3,6,3,5,3,5,9,4]

def UniqueMinSumArray(num_list):

    max=min(num_list)
    for i,V in enumerate(num_list):
        while (num_list.count(num_list[i])>1):
            if (max > num_list[i]+1) :
                num_list[i] = max + 1
            else:
                num_list[i]+=1
            max = num_list[i]
        i+=1
    return num_list

print (sum(UniqueMinSumArray(num_list1)))

您可以尝试使用您的数字列表,我相信它会为您提供正确的唯一最小数量。

答案 3 :(得分:0)

我也有同样的面试问题。但是我的答案是在JS中,以防有人感兴趣。

确保可以改进它以摆脱for循环。

Caused by: org.springframework.cloud.dataflow.rest.client.DataFlowClientException: Can not find package 'input-to-event-message-channel', version 'null'
    at org.springframework.cloud.dataflow.rest.client.VndErrorResponseErrorHandler.handleError(VndErrorResponseErrorHandler.java:65) ~[spring-cloud-dataflow-rest-client-2.0.2.RELEASE.jar:2.0.2.RELEASE]