假设我有以下代码。
var numberToGetTo = 60;
var list = new[] {10, 20, 30, 40, 50};
我希望能够返回50& 10从列表到= 60。
如果numberToGetTo为100,我想要返回50,50。
如果numberToGetTo为85,我想返回50,40。
我想从列表中返回最少量的数字来获取“numberToGetTo”,同时保持最接近(等于或更高)的数字。
可以用Linq做这样的事吗?
答案 0 :(得分:13)
这是一个名为knapsack problem的NP完全问题。这意味着,你最好的方法不会是多项式时间。您可能需要强制解决方案。
答案 1 :(得分:6)
这是一个使用Linq尽可能干净的实现。它没有尝试优化大输入的性能。
我假设你不会将此算法用于大输入,因为问题是NP-Complete,因此清晰度是正确的目标。我的算法是O(n ^ 2),并在那里递归。
static IEnumerable<int> Knapsack(IEnumerable<int> items, int goal)
{
var matches = from i in items
where i <= goal
let ia = new[] {i}
select i == goal ? ia : Knapsack(items, goal - i).Concat(ia);
return matches.OrderBy(x => x.Count()).First();
}
答案 2 :(得分:2)
目前陈述的这个问题实际上是微不足道的。获得“等于或大于”目标的最简单方法是在列表中找到最大数量A,并将其粘贴在答案列表中N次,其中N是最低N,使得N * A> 1。目标。
我怀疑这不是原始海报真正想要的。如果问题被重述,以某种方式衡量各种答案的“亲密度”,并区分“更接近”的答案或数字较少的答案是否“更好”,那么它就变得更加困难。例如,如果目标是100,那么[55,55]的答案是否比[20,20,20,20,20]的答案更好或更差?
答案 3 :(得分:1)
背包问题,这可能会给你一个线索。
http://en.wikipedia.org/wiki/Knapsack_problem
我会说你可以创建一个包含实际算法的lambda表达式,但是你需要使用C#。使用'just linq'是不够的。
答案 4 :(得分:0)
这听起来类似于Subset sum problem,对于使用动态编程的小集合,可以在合理的时间内解决。这不是一个简单或常见的问题,因此您无法找到有用的Linq扩展方法:)
答案 5 :(得分:0)
我只是一起攻击这个,我相信有人可以改进。但这样做有用吗?
public class App
{
static void Main(string[] eventArgs)
{
var list = new[] {10, 20, 30, 40, 50};
var whatYouNeed = GetWhatYouNeed(list, 60, 60);
//what you need will contain 50 & 10
//whatYouNeed = GetWhatYouNeed(list, 105,105);
//what you need will contain (50,50, 10)
}
private static IList<int> _whatYouNeed = new List<int>();
static IEnumerable<int> GetWhatYouNeed(IEnumerable<int> list, int goal, int amountRequired)
{ //this will make sure 20 is taken over 10, if the goal is 15. highest wins
var intYouNeed = list.OrderBy(x => Math.Abs(amountRequired - x)).FirstOrDefault(x => x > amountRequired);
if (intYouNeed == 0) intYouNeed = list.OrderBy(x => Math.Abs(amountRequired - x)).FirstOrDefault();
_whatYouNeed.Add(intYouNeed);
if (_whatYouNeed.Sum() < goal)
{
int howMuchMoreDoYouNeed = goal - _whatYouNeed.Sum();
GetWhatYouNeed(list, goal, howMuchMoreDoYouNeed);
}
return _whatYouNeed;
}
}
我有点懒惰,将两个值传递给GetWhatYouNeed,但你明白了。