我在面试问题中看到了这一点,
给定排序顺序字符串,系统会要求您根据给定的排序顺序字符串对输入字符串进行排序
例如,如果排序顺序字符串是dfbcae
输入字符串为abcdeeabc
输出应为dbbccaaee
。
关于如何以有效的方式做到这一点的任何想法?
答案 0 :(得分:6)
Counting Sort选项非常酷,当要排序的字符串与排序顺序字符串相比较长时,它很快。
算法复杂度为O(n)
,其中n
是要排序的字符串的长度。正如维基百科文章所解释的那样,我们能够超越基于标准比较的排序的下限,因为这不是基于比较的排序。
这是一些伪代码。
char[26] countArray;
foreach(char c in sortTarget)
{
countArray[c - 'a']++;
}
int head = 0;
foreach(char c in sortOrder)
{
while(countArray[c - 'a'] > 0)
{
sortTarget[head] = c;
head++;
countArray[c - 'a']--;
}
}
注意:此实现要求两个字符串仅包含小写字符。
答案 1 :(得分:3)
这是一个易于理解的算法,具有不错的算法复杂性。
对于排序顺序字符串
中的每个字符这是O(n*m)
,其中n
是要排序的字符串的长度,m
是排序顺序字符串的长度。我们能够击败基于比较的排序的下限,因为该算法并不真正使用比较。像Counting Sort一样,它依赖于你有一个预定义的有限外部排序集。
这是一些伪代码:
int head = 0;
foreach(char c in sortOrder)
{
for(int i = head; i < sortTarget.length; i++)
{
if(sortTarget[i] == c)
{
// swap i with head
char temp = sortTarget[head];
sortTarget[head] = sortTarget[i];
sortTarget[i] = temp;
head++;
}
}
}
答案 2 :(得分:0)
使用二分搜索查找不同字母之间的所有“分割点”,然后直接使用每个分段的长度。这将比天真的计数排序渐近更快,但实现起来会更难:
使用大小为26 * 2的数组存储每个字母的开头和结尾;
检查中间元素,看它是否与剩下的元素不同。如果是这样,那么这是中间元素的开始,并且在它之前的元素结束;
丢弃具有相同开头和结尾的片段(如果有的话),递归地应用此算法。
由于最多有25个“分裂”,因此您不必搜索超过25个segemnts,并且对于每个分段,它都是O(logn)。由于这是constant * O(logn)
,因此算法为O(nlogn)。
当然,使用计数排序会更容易实现:
使用大小为26的数组来记录不同字母的数量;
扫描输入字符串;
以给定的排序顺序输出字符串。
这是O(n),n是字符串的长度。
答案 3 :(得分:0)
在Python中,您只需创建一个索引并在比较表达式中使用它:
order = 'dfbcae'
input = 'abcdeeabc'
index = dict([ (y,x) for (x,y) in enumerate(order) ])
output = sorted(input, cmp=lambda x,y: index[x] - index[y])
print 'input=',''.join(input)
print 'output=',''.join(output)
给出了这个输出:
input= abcdeeabc
output= dbbccaaee
答案 4 :(得分:0)
面试问题通常与思考过程有关,通常不太关心语言功能,但无论如何我无法抗拒发布VB.Net 4.0版本。
“高效”可能意味着两件事。第一个是“什么是使计算机执行任务的最快方法”,第二个是“我们可以完成任务的最快速度”。它们可能听起来相同,但第一个可能意味着微优化,如int
vs short
,运行计时器来比较执行时间,并花费一周时间从算法中每毫秒调整一次。第二个定义是关于创建执行任务的代码需要多少人工时间(希望在合理的时间内)。如果代码A的运行速度比代码B快20倍,但代码B花费了1/20的时间来编写,具体取决于计时器的粒度(1ms vs 20ms,1周vs 20周),每个版本都可以被视为“高效”
Dim input = "abcdeeabc"
Dim sort = "dfbcae"
Dim SortChars = sort.ToList()
Dim output = New String((From c In input.ToList() Select c Order By SortChars.IndexOf(c)).ToArray())
Trace.WriteLine(output)
答案 5 :(得分:0)
以下是我对问题的解决方案
import java.util.*;
import java.io.*;
class SortString
{
public static void main(String arg[])throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
// System.out.println("Enter 1st String :");
// System.out.println("Enter 1st String :");
// String s1=br.readLine();
// System.out.println("Enter 2nd String :");
// String s2=br.readLine();
String s1="tracctor";
String s2="car";
String com="";
String uncom="";
for(int i=0;i<s2.length();i++)
{
if(s1.contains(""+s2.charAt(i)))
{
com=com+s2.charAt(i);
}
}
System.out.println("Com :"+com);
for(int i=0;i<s1.length();i++)
if(!com.contains(""+s1.charAt(i)))
uncom=uncom+s1.charAt(i);
System.out.println("Uncom "+uncom);
System.out.println("Combined "+(com+uncom));
HashMap<String,Integer> h1=new HashMap<String,Integer>();
for(int i=0;i<s1.length();i++)
{
String m=""+s1.charAt(i);
if(h1.containsKey(m))
{
int val=(int)h1.get(m);
val=val+1;
h1.put(m,val);
}
else
{
h1.put(m,new Integer(1));
}
}
StringBuilder x=new StringBuilder();
for(int i=0;i<com.length();i++)
{
if(h1.containsKey(""+com.charAt(i)))
{
int count=(int)h1.get(""+com.charAt(i));
while(count!=0)
{x.append(""+com.charAt(i));count--;}
}
}
x.append(uncom);
System.out.println("Sort "+x);
}
}
答案 6 :(得分:0)
这是我的版本,它是O(n)及时。我可以使用一个常量大小的char数组,而不是unordered_map。我...,E。假设输入字符串包含所有ASCII小字符,char char_count[256]
(并且已完成++char_count[ch - 'a']
)。
string SortOrder(const string& input, const string& sort_order) {
unordered_map<char, int> char_count;
for (auto ch : input) {
++char_count[ch];
}
string res = "";
for (auto ch : sort_order) {
unordered_map<char, int>::iterator it = char_count.find(ch);
if (it != char_count.end()) {
string s(it->second, it->first);
res += s;
}
}
return res;
}
答案 7 :(得分:0)
private static String sort(String target, String reference) {
final Map<Character, Integer> referencesMap = new HashMap<Character, Integer>();
for (int i = 0; i < reference.length(); i++) {
char key = reference.charAt(i);
if (!referencesMap.containsKey(key)) {
referencesMap.put(key, i);
}
}
List<Character> chars = new ArrayList<Character>(target.length());
for (int i = 0; i < target.length(); i++) {
chars.add(target.charAt(i));
}
Collections.sort(chars, new Comparator<Character>() {
@Override
public int compare(Character o1, Character o2) {
return referencesMap.get(o1).compareTo(referencesMap.get(o2));
}
});
StringBuilder sb = new StringBuilder();
for (Character c : chars) {
sb.append(c);
}
return sb.toString();
}
答案 8 :(得分:0)
在C#中,我只使用IComparer接口并将其保留给Array.Sort
{{1}}