【问题标题】:Make Array Contiguous Subsequence By Adding Digits通过添加数字使数组连续子序列
【发布时间】:2021-10-01 15:20:33
【问题描述】:

假设我在数组中有一系列元素为 [2 2 3 4 5 6 7 8 9 0]。我可以在数组中的数字之前或之后或中间添加任何数字,以使数组变得连续并返回最小的最小元素。对于上述数组,我们可以将其设为 [21 22 23 24 25 26 27 28 29 30],最小元素为 21。 数字将始终为正数,而不是负数,并且浮点数将存在于数组中。

另一个例子 - [6 7 8 9 4 4 2 3] 答案 - [36 37 38 39 40 41 42 43] 最小值 - 36

【问题讨论】:

  • 你能解释一下你的算法吗
  • @Sujay 你是在问我的方法还是关于问题?如果你问我的方法,我的想法是,如果 2 个连续元素与第二个示例中的相同,则取值小于上述情况 4 是连续 2 次,所以我取了 3 次。我是编码新手,还在学习所以不知道在此之外并受到打击
  • @PrantaPalit。我认为是因为有 2 个连续的 2。所以基数是 2。
  • 如果不增加一些约束和放松其他约束,这个问题就无法解决。例如,迷你数组 [5, 3] 可以以超过 1 种方式连续,例如 [52, 53] 和 [35, 36]。需要一些最小约束。此外,某些序列没有解决方案,除非将“插入数字”更改为“插入任意数量的数字”。考虑例如 [123, 5]。像 [1234,1235] 这样的解决方案目前是无效的,因为它需要每个数字插入 3 个数字。问题涉及“元素”数组,但我怀疑输入为负数,浮点数是允许的。
  • 请更新您的问题描述。它说“一个数字”,而不是“任意数量的数字”。它说“返回(结果数组的)最小元素”,而不是“返回可能的最小最小元素”它谈论“(任何)元素”,而您的 cmets 突然将其更改为“非负整数”。我很抱歉我在“连续”中的类型,特别是因为连续属性是 & 是唯一从当前描述中清楚的属性。在此期间我已经解决了。如果你清理你的描述,我会发布它。

标签: python arrays python-3.x list algorithm


【解决方案1】:

以下代码是一个解决方案。它没有经过彻底的测试,但它完成了问题陈述中给出的示例应该做的事情。

test(new int[]{2 ,2 ,3 ,4, 5, 6, 7, 8 ,9 ,0});
// output: [21, 22, 23, 24, 25, 26, 27, 28, 29, 30], min = 21
test(new int[]{6, 7, 8, 9, 4, 4, 2, 3}); 
// output: [36, 37, 38, 39, 40, 41, 42, 43], min = 36

它是用 Java 编写的,但转换成另一种语言应该不难。

这是测试方法:

public void test(int[] arr)
{
    int min = modifyAndMinimize(arr);
    System.out.println(Arrays.toString(arr) + ", min = " + min);
}

数组修饰符:

/**
 * Modifies the numbers (which must be non-negative) in arr such that the new version
 * is contiguous, meaning that for every subsequence [u, v], v - u = 1.
 * The only type of modification that is applied is to insert digits into the elements of arr.
 * This can be done in many ways, but this function chooses the way that results in
 * the smallest possible first element (which this function returns).
 */
public int modifyAndMinimize(int[] arr) {
    for (int i = 0; i < arr.length - 1; i++) {
        int u = arr[i], v = arr[i + 1];
        int minU = modifyAndMinimize(3, u, v, "", "", 1); // hardcoded 3 out of laziness, but it's really a function of the number of digits of u and v
        if (v != minU + 1)
            arr[i + 1] = minU+ 1;
        if (u != minU) {
            arr[i] = minU;
            i = -1; // lazy way of moving back to fix the previous numbers
        }
    }
    return arr[0];
}

现在是关键,即“修复”两个连续元素的函数(想法很简单,但实现起来很棘手,而且我昨天发现的深夜无法调试):

/** 
 * Finds the smallest u' and v' such that v' - u' = diff, where u' and v' are modified versions
 * of u and v obtained by inserting digits.
 *
 * The approach is essentially the common subtraction algorithm, but instead of computing the
 * result of v - u, it's given the result and asked to compute u' and v' such that v' - u'
 * is the result (diff).
 */
public int modifyAndMinimize(int maxDepth, int u, int v, String doneU, String doneV, int diff) {
    if (maxDepth < 0) return Integer.MAX_VALUE;

    // if v - u == diff, we're done
    if (v - u == diff)
        return Integer.parseInt(u + doneU);

    // v and/or u need to be modified, but perhaps their last digits are already ok
    if ((v - u - diff) % 10 == 0)
        return modifyAndMinimize(maxDepth - 1, u / 10, v / 10, u % 10 + doneU, (v % 10) + doneV, diff / 10);

    // they're not ok. To fix this, try appending the appropriate digit to u and try appending
    // the appropriate digit to v. Choose the option that results in the smallest modified u.

    int appendToU = v % 10 - diff;
    int carry = appendToU / 10;
    appendToU %= 10;
    if (appendToU < 0) {
        appendToU += 10;
        carry--;
    }
    int option1 = modifyAndMinimize(maxDepth - 1, u, v / 10, appendToU + doneU, (v % 10) + doneV, diff / 10 - carry);

    int appendToV = u % 10 + diff;
    carry = appendToV / 10;
    appendToV %= 10;
    if (appendToV < 0) {
        appendToV += 10;
        carry--;
    }
    int option2 = modifyAndMinimize(maxDepth - 1, u / 10, v, (u % 10) + doneU, appendToV + doneV, diff / 10 + carry);

    return Math.min(option1, option2);
}

很可能有一种更好的方法,而不是使用蛮力来决定是否应该将数字添加到 u 或 v (它在数字数量上是指数的,所以它在数字本身是线性的)。如果是这样,我错过了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-28
    • 2015-07-01
    • 2014-04-30
    相关资源
    最近更新 更多