Algorithm 面试难题:一个坏掉的计算器

Algorithm 面试难题:一个坏掉的计算器,algorithm,Algorithm,时间限制:2秒/堆栈限制:256MB/内存限制:256MB 问题 戴夫的计算器坏了。当显示超过K个不同数字时,它将停止 Dave想输入一个整数A,但如果他输入的数字正确,计算器可能会停止。相反,他输入的是不会使计算器停止的最接近的整数 输出Dave输入与整数A之间的差值 输入 输入将以标准输入的以下格式给出 A K 在第一行,您将得到整数A(1≦A.≦10^15),Dave要输入的整数,后跟空格和K(1)≦K≦10) ,他的计算器能识别的不同位数 输出 在一行中输出Dave输入与整数A之间

时间限制:2秒/堆栈限制:256MB/内存限制:256MB

问题 戴夫的计算器坏了。当显示超过K个不同数字时,它将停止

Dave想输入一个整数A,但如果他输入的数字正确,计算器可能会停止。相反,他输入的是不会使计算器停止的最接近的整数

输出Dave输入与整数A之间的差值

输入

输入将以标准输入的以下格式给出

A K
  • 在第一行,您将得到整数A(1≦A.≦10^15),Dave要输入的整数,后跟空格和K(1)≦K≦10) ,他的计算器能识别的不同位数
输出

在一行中输出Dave输入与整数A之间的最小差值。确保在输出的末尾插入换行符


输入示例1

1234 2
12
输出示例1

1234 2
12
在这种情况下,Dave最多只能使用2个不同的数字。他将输入最接近的整数1222,因此差值为12


输入示例2

7328495 10
0
输出示例2

7328495 10
0
在这种情况下,戴夫的计算器一点也没有坏。他可以按原样输入给定的整数A


输入示例3

800000 1
22223
输出示例3

800000 1
22223
Dave只能使用一个数字,因此7777是最接近的整数


输入示例4

262004 2
218
输出示例4

262004 2
218
最接近的整数是262222


我已经用蛮力解决了这个问题

我尝试了所有可能的情况,我在1编辑N2

在每个步骤中,检查是否:

a) 将关闭集的可能位数设置为小于当前位数,然后最大化剩余位数,这比当前答案更好

b) 将最接近的可能数字放在更大的位置,然后放在当前位置,然后最小化剩余数字,这比当前答案更好


然后,如果可能,将相同的数字放入下一个数字

第一部分是:选择结果中使用的k位(10个可能的数字中的哪一个
通过一点数学(二项式系数),很容易计算出数字
给定k可能的不同数字组合。
最多可选择252种可能性(如果k=5,则为252种,否则不太多)

如果不清楚我在说什么:对于k=2,有
01,02,03,…09,12,13,…,19,23,24,…,89

不,例如11,因为它只有1,但k=2允许两个不同的数字。
没有,例如90,因为它与09、91=19等相同。
对于k=5,这些可能组合的计数为252,并且不会变大

查找当前k的所有(最多)252种可能性
在循环中迭代它们应该不会太难

对于每个可能性,请执行以下操作:
{

在循环中,我们有A、K和当前选择的有效数字
对于解决方案(当然,后者在循环的每次迭代中都有所不同)
以A=12899,K=3,数字123为例。
现在搜索不允许的a的第一个数字(从左到右)。
在本例中,这将是12899,因为它的左1和左2是允许的

如果有下一个允许的较低数字(2),则将该数字(8)替换为下一个允许的较低数字(2)
并用可能的最高数字(3)替换其右边的所有内容。
12899=>12399=>12333
将结果12333保存在数组中的某个位置等。
如果没有下一个较低的可能数字,则不执行任何操作(不向数组发送任何内容)

(带进位的适当加法将在更改后的数字左边引入一个新数字,
ie.无效。将找到具有此新数字的解决方案
当循环到达该数字时)

然后在另一个方向重复同样的事情:
用下一个更高的数字替换找到的数字
所有的东西都是最低的。这也在数组中,
当然,只有在有下一个更高的可能数字时。
在12899的情况下,8的唯一较高替代值是9,
但9是不可能的(只有123)

}

整个循环完成后(每次迭代都产生
最多两个新数组项),您最多有502个可能的问题解决方案。
剩下要做的唯一一件事就是检查哪种溶液最好(即计算差值

在每个步骤中,您可以使用所需的数字、数字+1(mod 10)、数字-1(mod 10)或您以前使用过的任何数字。数字用完后,只能使用以前使用过的数字

这将创建一棵树。在每个步骤中,获取当前状态并计算下一级别中所有可能的新状态

您可以通过删除任何后续步骤来修剪树,这些步骤的增量与后续步骤中最小的增量之间的距离超过一定距离

这本质上是一个线性规划问题

下面是完整的算法!也许有人可以对修剪哪些树枝的决定进行微调,使之更快

using System.IO;
using System;
using System.Collections.Generic;
using System.Linq;

public static class Converter
{
    public static int ToInt(this IEnumerable<int> values)
    {
        return values.Aggregate(0, (total, v) => total * 10 + v);
    }

    public static IEnumerable<int> ToList (this int value)
    {
        if (value == 0) return Enumerable.Empty<int>();
        else return value.ToString().Select(x => (int)x - '0').ToList();
    }
}


class Program
{
    static void Main(string[] args)
    {
        //int desired = 262004;
        //int digits = 2;

        int desired = 800000;
        int digits = 1;

        IEnumerable<State> currentStates = new[] { new State(0, 0, desired, digits) };

        foreach (var digit in desired.ToList())
        {
            var nextStates = currentStates.SelectMany(x => x.NextPossibleStates());
            foreach (var state in nextStates.OrderBy(s => s.Delta()).Take(10))
            {
                Console.WriteLine(state.ToString());
            }
            currentStates = nextStates;
            Console.WriteLine("------------");
        }

        Console.ReadKey();
    }

    public class State
    {
        int index;
        int current;
        int desired;
        int digitsRemaining;

        private int desiredToNow()
        {
            return desired.ToList().Take(index).ToInt();
        }

        public int Delta()
        {
            return Math.Abs(desiredToNow() - current);
        }

        public State(int index, int current, int desired, int digitsRemaining)
        {
            this.index = index;
            this.current = current;
            this.desired = desired;
            this.digitsRemaining = digitsRemaining;
        }

        private State Next (int nextDigit, int digitsRemaining)
        {
            return new State(this.index + 1, this.current * 10 + nextDigit, this.desired, digitsRemaining);
        }

        private IEnumerable<int> NextPossibleDigitsWithDuplicates()
        {
            if (this.digitsRemaining > 0)
            {
                int nextDesiredDigit = desired.ToList().Skip(index).First();
                yield return nextDesiredDigit;
                yield return (nextDesiredDigit + 9) % 10;
                yield return (nextDesiredDigit + 1) % 10;
            }
            // Any previously used digit is OK
            foreach (int i in this.current.ToList())
                yield return i;
        }

        public IEnumerable<State> NextPossibleStates()
        {
            var possibles = this.NextPossibleDigitsWithDuplicates().Distinct();
            var possiblesUsingExistingDigits = possibles.Where(p => this.current.ToList().Contains(p));
            var possiblesUsingNewDigits = possibles.Where(p => !this.current.ToList().Contains(p));

            var states = possiblesUsingExistingDigits.Select(p => Next(p, this.digitsRemaining))
                .Concat(possiblesUsingNewDigits.Select(p => Next(p, this.digitsRemaining - 1)))
                .ToList();

            var bestDelta = states.Min(s => s.Delta());
            // Now reject any that can never be better
            // Guessing on the '2' here ...
            var validStates = states.Where(s => s.Delta() < bestDelta + 2);
            return validStates;
        }

        public override string ToString()
        {
            return this.current + " d=" + this.Delta() + " remaining " + this.digitsRemaining;
        }
    }
}
使用System.IO;
使用制度;
使用System.Collections.Generic;
使用System.Linq;
公共静态类转换器
{
公共静态int-ToInt(此IEnumerable值)
{
返回值。聚合(0,(总计,v)=>总计*10+v);
}
公共静态IEnumerable ToList(此int值)
{
if(value==0)返回Enumerable.Empty();
else返回值.ToString().Select(x=>(int)x-'0').ToList();
}
}
班级计划
{
静态void Main(字符串[]参数)
{
//期望的整数=262004;
//整数位数=2;
期望的整数=800000;
在里面