您的位置:首页 > 职场人生

一个朋友面试时遇到的算法题(怎么组合后得到最大整数)

2014-10-11 10:22 441 查看
  首先,这篇的标题是我借来的,两周前,我看过MrWrong发的一篇帖子(http://www.cnblogs.com/MrWrong/p/3986158.html),初看时感觉就是一个排列问题,然后洒洒水般的写了一段,结果被版主指出误点,当时我真的头蒙了,坐在那里两个小时,想不出比较好的方法(全排列,然后比较大小的方法排除,这个不借鉴,如果有十个不一样的元素,全排列方法有3628800中,如果在多一位元素就是39916800,已经比前一个多十倍了,需要的内存指数上升),然后又碰到十一国庆,也把这个问题滞后了(当初给版主回复:这个问题很好,稍等,一等就是两周...),昨天才想到还有这么回事,回家就认真看了看问题,小子虽然不才,但是也把它解决了。

题目如下:

一个正整数数组:如, 14 32 133 152

将其串起来得到能表示的最大整数(这里就是3215214133)

  这道题原贴主提供的几种方法,当时我看看也是云里雾里的,不明觉厉。可能技术层次上有差异吧,毕竟人家是只老雕,咱不过是只小鸟。

这道题我采用的方法:集合分类;从首到尾逐个字符处理,排除非最大字符的元素。(中间集合元素会衍生)

处理过程看下代码,比较清晰:

//如果长度比需求的小,向后补【补的时候注意已经存在的项不再添加】
CheckLength(curIndex, ref eList);
//找出最大字符
Char maxChar = GetMaxChar(eList, curIndex);
//删除非最大字符
DelNoMaxChar(curIndex, maxChar, ref eList);

举例吧:14 32 133 152

1.分集合(集合模型定义{ {可能最大元素} , {剩余元素} } ):{ {14,32,133,152} , { } } ,从第一位开始检查。

2.首先检查每个字符的长度是否足够1(看来都足够长)

3.然后找出最大字符 maxChar = 3

4.将首字符非3的移到其他集合{{32} , {14,133,152}}

5.检查第二字符,由于现在最大集合只有一个元素,所以就是它自己,现在集合仍是{{32} , {14,133,152}}

6.检查第三字符,由于最大集合32不足三位,需要补数,补后集合{ {32|14,32|133,32|152} , { } }

7.找出第三个字符最大 maxChar = 1 ,都是1 ,集合保持不变 { {32|14,32|133,32|152} , { } }

8.找出第四个字符最大 maxChar = 5, 最大集合排除非5 ,执行后集合{ {32|152} , {14,133} }

.... 之后方法如上。

注:代码中部分实现跟以上稍有不同,但是主要解决方式是相同的。

以下是源代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace ConsoleApplication2
{
public class Cluster
{
/// <summary>
/// 已使用
/// </summary>
public List<string> UseList;
/// <summary>
/// 未使用
/// </summary>
public List<string> RemainingList;

private string stringValue = "";
public string StringValue
{
get { return stringValue; }
}

public Cluster()
{
this.UseList = new List<string>();
this.RemainingList = new List<string>();
}

public Cluster(string stringValue)
: this()
{
this.stringValue = stringValue;
}

public void Add(string item)
{
int index = -1;
for (int i = 0; i < RemainingList.Count; i++)
{
if (RemainingList[i] == item)
{
index = i;
}
}

if (index >= 0)
{
RemainingList.RemoveAt(index);
UseList.Add(item);
this.stringValue += item;
}
else
{
throw new ArgumentException("剩余中不存在该元素:" + item);
}
}

public Cluster Clone()
{
Cluster ret = new Cluster(this.stringValue);
ret.UseList.AddRange(this.UseList.ToArray());
ret.RemainingList.AddRange(this.RemainingList.ToArray());

return ret;
}
}

public class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += (s, e) => { Console.WriteLine(e.ExceptionObject.ToString()); Console.ReadKey(); };

//List<string> orgList = new List<string>() { "33", "48", "5", "53", "54", "544", "54444", "546", "55" };
List<string> orgList = null;

if (args.Length > 0)
{
orgList = new List<string>();
orgList.AddRange(args);
}
else
{
orgList = new List<string>() { "33", "48", "5", "53", "54", "544", "54444", "546", "55" };
}

CheckNum(orgList);
List<Cluster> eList = new List<Cluster>();
//连接后的字符串最大长度
int maxLength = 0;
foreach (var item in orgList)
maxLength += item.Length;

foreach (var item in orgList)
{
Cluster el = new Cluster();
el.RemainingList.AddRange(orgList.ToArray());
el.Add(item);

eList.Add(el);
}

for (int curIndex = 0; curIndex < maxLength; curIndex++)
{
//如果长度比需求的小,向后补【补的时候注意已经存在的项不再添加】
CheckLength(curIndex, ref eList);
//找出最大字符
Char maxChar = GetMaxChar(eList, curIndex);
//删除非最大字符
DelNoMaxChar(curIndex, maxChar, ref eList);
}

var list = eList;

Console.WriteLine(eList[0].StringValue);
Console.ReadKey();
}

static void DelNoMaxChar(int index, char maxChar, ref List<Cluster> list)
{
for (int i = list.Count - 1; i >= 0; i--)
{
Cluster el = list[i];
if (el.StringValue[index] < maxChar)
{
list.RemoveAt(i);
}
}
}

static void CheckNum(List<string> list)
{
Regex regNumber = new Regex(@"^\d+$");
foreach (var item in list)
{
if (!regNumber.IsMatch(item))
{
throw new ArgumentException("数组中有非数字符号: " + item);
}
}
}

static void CheckLength(int index, ref List<Cluster> list)
{
for (int i = 0; i < list.Count;)
{
if (list[i].StringValue.Length <= index)
{
Cluster curCluster = list[i];

foreach (var item in curCluster.RemainingList)
{
#region 去除可能重复
bool flag = false; //重复标志
string stringvalue = curCluster.StringValue + item;

for (int j = 0; j < list.Count; j++)
{
if (String.Equals(list[j].StringValue, stringvalue))
{
flag = true;
break;
}
}
#endregion

if (!flag)
{
Cluster clone = curCluster.Clone();
clone.Add(item);
list.Add(clone);
}
}

list.RemoveAt(i);
continue;
}
i++;
}
}

static Char GetMaxChar(List<Cluster> list, int index)
{
Char targetChar = '\0';

for (int i = 0; i < list.Count; i++)
{
if (list[i].StringValue[index] > targetChar)
targetChar = list[i].StringValue[index];
}

if (targetChar != '\0')
return targetChar;
else
throw new Exception("查找最大字符时出错");
}
}
}


源代码

从此向下为后补内容,觉得应该加上去,很多人来讨论,当然方法一个比一个好,以下方法是我精简出来的一套好方法,跟大家养养眼,呵呵:

var list = new List<string>() { "33", "48", "5", "53", "54", "544", "54444", "546", "55" };
list.Sort(delegate(string x,string y){return string.CompareOrdinal(y + x,x + y);});
string result = string.Join("", list.ToArray());
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐