一个朋友面试时遇到的算法题(怎么组合后得到最大整数)
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} }
.... 之后方法如上。
注:代码中部分实现跟以上稍有不同,但是主要解决方式是相同的。
以下是源代码:
源代码
从此向下为后补内容,觉得应该加上去,很多人来讨论,当然方法一个比一个好,以下方法是我精简出来的一套好方法,跟大家养养眼,呵呵:
题目如下:
一个正整数数组:如, 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());
相关文章推荐
- 一个朋友面试时遇到的算法题(怎么组合后得到最大整数)
- 给定一个整数(字符串也适用)序列,重新排列,得到最大的结果,比如31,3,35,7,9根据排列后得到组合 9735331,返回的是string类型
- 假如一个数组存储了一个股票,在一天交易窗口内各时间点的股票价格(正整数),只允许一次买入和一次卖出,请提供一个算法,计算出通过买入和卖出可以得到的最大利润
- 算法8:一个整数数组里怎么同时找最大和最小的数,尽量优化比较次数
- 假如一个数组存储了一个股票,在一天交易窗口内各时间点的股票价格(正整数),只允许一次买入和一次卖出,请提供一个算法,计算出通过买入和卖出可以得到的最大利润
- 【微软谷歌面试100题--【45】一个整数数组,长度为n,将其分为m 份,使各份的和相等,求m 的最大值
- 贪心算法——输入任意一个正整数N,将其分成多个互不相同的整数,和为N,乘积最大
- 在一个整数数组中寻找符合A+B=C的组合,使C为最大
- 基础算法测试——生成一个1-10之间的随机整数组合
- 面试题:一个整型数组中各元素排列组合得到的最大的一个数 ,比如,1,3,9,11,23,233,911 要得到:9,911,3,233,23,11,1
- 微软等数据结构+算法面试100题(6)--写一个函数,检查字符是否是整数,如果是,返回其整数值
- 算法习题45:对于一个整数矩阵,存在一种运算,对矩阵中任意元素加一时,需要其相邻(上下左右)某一个元素也加一;;;一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值
- 基础算法测试——生成一个1-10之间的随机整数组合
- /*C++任意输入一个整数,再把它的各位数字重新组合一个新的整数,使其值最大*/
- 每日一道算法题:一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值
- 算法函数:得到一个字符串中的最大长度的数字
- 基础算法测试——生成一个1-10之间的随机整数组合
- 基础算法测试——生成一个1-10之间的随机整数组合
- 算法(求对输入的N个数进行加法或减法运算,得到最小的正整数的组合.)
- 软件开发者面试百问-----有一个数组,里面是从1到1,000,000的整数,其中有一个数字出现了两次,你怎么找出那个重复的数字?