锁定老帖子 主题:给大家出道题,算法的
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (17)
|
|
---|---|
作者 | 正文 |
发表时间:2012-02-09
最后修改:2012-02-09
1.先安字符串长度分组。。length为key,StringList为value .
2.遍历每个分组。每个字符串拆分成字符数组重新排序后再合并成字符串,保存一个新字符串组。 3.将重组后字符串作为key,原串作为value,put入map,put之前先get,有相同的则保存为同一组。 觉得还是可行的。。请指点。。。。 重新改造一下: 每个字符串拆分成字符数组重新排序后再合并成字符串 public static void print(){ String [] ss = new String[]{"hat", "top", "potter", "pot", "pier", "ripe"}; String [] newss = new String[ss.length]; //保排序后的新字符串数组 Map<String , List<String>> res = new HashMap<String,List<String>>(); for(int i = 0 ; i < ss.length ; i ++){ char[] cs = ss[i].toCharArray(); Arrays.sort(cs); newss[i] = new String(cs) ; List<String> isE = res.get(newss[i]); if(isE == null || isE.size() <= 0 ){ //不存在同样的记录 isE = new ArrayList<String>(); } isE.add(ss[i]); res.put(newss[i], isE); } Set<String> keySet = res.keySet(); for(String s : keySet){ List<String> print = res.get(s); StringBuilder sb = new StringBuilder(s+":"); for(String sprint : print){ sb.append(sprint).append(","); } System.out.println(sb.toString()); } } 结果为: eoprtt:potter, aht:hat, opt:top,pot, eipr:pier,ripe, |
|
返回顶楼 | |
发表时间:2012-02-09
最后修改:2012-02-09
您这个应该就是桶排序吧,不错~
kidding87 写道 jdk用的是归并排序,这里有些不合适,效率不高
改用先统计每个字母的数量再组装字符串,效率提高一倍 public static String sort(String s){ //26个字母 short[] t =new short[26]; char c[]=s.toCharArray(); for(short i=0;i<c.length;t[c[i++]-'a']++) ; for(short i=0,j=0;i<26&&j<c.length;i++){ for(short k=1;k<=t[i];k++){ c[j++]=(char)(i+'a'); } } return new String(c); } [\code] 下面有就有个问题了,对于程序来说,字符串是什么,还不是char[],这里我们再思考下,反正都是要比较的,我直接把上面的那个short []t丢出来比较是不是更快 public class Comparable { public short[] t; public Comparable(String s){ t=PP.sort2(s); } @Override public boolean equals(Object paramObject) { if(paramObject==null) return false; if(paramObject instanceof Comparable){ Comparable cast = (Comparable)paramObject; if(cast.t.length!=this.t.length) return false; for(int i=0;i<cast.t.length;i++){ if(cast.t[i]!=this.t[i]) return false; } return true; } return false; } @Override public int hashCode() { int r=0; for(int i=0;i<t.length;i++){ r+=r*31+t[i]; } return r; } } [\code] 完整测试代码 public class PP { public static void main(String[] args) { String s="cccabcfdjfdisojfiosfuqjofjidosjfasofusafus"; double time = System.currentTimeMillis(); for(int i=0;i++<1000000;Arrays.sort(s.toCharArray())); double time2 = System.currentTimeMillis(); System.out.println((time2-time)); for(int i=0;i++<1000000;sort(s)); double time3 = System.currentTimeMillis(); System.out.println(time3-time2); for(int i=0;i++<1000000;sort2(s)); double time4 = System.currentTimeMillis(); System.out.println(time4-time3); String str=new String(s); double time5 = System.currentTimeMillis(); for(int i=0;i++<1000000;s.equals(str)); double time6 =System.currentTimeMillis(); System.out.println(time6-time5); Comparable c1= new Comparable(s); Comparable c2 =new Comparable(s); double time7 = System.currentTimeMillis(); for(int i=0;i++<1000000;c1.equals(c2)); double time8= System.currentTimeMillis(); System.out.println(time8-time7); } public static String sort(String s){ //26个字母 short[] t =new short[26]; char c[]=s.toCharArray(); for(short i=0;i<c.length;t[c[i++]-'a']++) ; for(short i=0,j=0;i<26&&j<c.length;i++){ for(short k=1;k<=t[i];k++){ c[j++]=(char)(i+'a'); } } return new String(c); } public static short[] sort2(String s){ //26个字母 short[] t =new short[26]; char c[]=s.toCharArray(); for(short i=0;i<c.length;t[c[i++]-'a']++) ; return t; } } class Comparable { public short[] t; public Comparable(String s){ t=PP.sort2(s); } @Override public boolean equals(Object paramObject) { if(paramObject==null) return false; if(paramObject instanceof Comparable){ Comparable cast = (Comparable)paramObject; if(cast.t.length!=this.t.length) return false; for(int i=0;i<cast.t.length;i++){ if(cast.t[i]!=this.t[i]) return false; } return true; } return false; } @Override public int hashCode() { int r=0; for(int i=0;i<t.length;i++){ r+=r*31+t[i]; } return r; } } [\code] 结果 1827.0 968.0 410.0 225.0 142.0 (1827+225)/(410+142)≈3.7 差不多比自己写的耗时多3.7倍 不知道大家能不能理解,利用质数方法是不错,但是字符串长度过大的话,BigInteger的性能太差,它内部其实还是数组,依次遍历相乘再进位的算法,很慢 |
|
返回顶楼 | |
发表时间:2012-02-09
bylijinnan 写道 您这个应该就是桶排序吧,不错~
哈哈,我还不知道什么是桶排序 这个算法的时间复杂度是O(n)左右;归并是log(n);而他们提出的质数算法,查找效率 就是O(1) ,我也牺牲了空间来做键值 不过质数算法的对于大的字符串,空间上不比我这个少,计算键值,键值比对这个性能急剧下降 关键点其实并不只是排序; 而是将排序后的字符串转义,这样的比较速度效率很高 |
|
返回顶楼 | |
发表时间:2012-02-09
将字符串转成字节数组做,排序是按照字节数组的第一个由小到大排序,找出相同的字符串是按照字节数组相加的总和去比较。
|
|
返回顶楼 | |
发表时间:2012-02-09
最后修改:2012-02-09
先对每个单词内部按顺序排序,
比如: hat -> aht top -> opt pot -> opt potter -> eoprtt pier -> eipr ripe -> eipr 然后再按排序好的分组,如何? |
|
返回顶楼 | |
发表时间:2012-02-13
给个erlang写的算法,大家评价下
-module(ksort). -vsn(1.0). -author({"jian fan,TianZe Information Inc."}). -purpose("example of ksort"). -export[(getlist/1)]. -export[(qsort/1)]. -export[(xsort/2)]. %sort the string in list qsort([]) -> []; qsort([H|T]) -> [lists:sort(H)]++ qsort(T). %get the list 1 getlist([]) -> []; getlist([H|T]) -> [X|L] = D = lists:usort(qsort([H|T])),io:format("getlist1~p~n",[D]), getlist([H|T],[X|L]). %get the list 2 getlist([H|T],[]) -> []; getlist([H|T],[X|L]) -> D=xsort([H|T],X),io:format("getlist2~p ",[D]), getlist([H|T],L). %get the string list which sort string is equal with some string. xsort([],String) -> []; xsort([X|L],String) -> D=qsort([X]), if D == [String] -> io:format("xsort~p~n",[X]),[X]; true -> "" end++ xsort(L,String). ksort:getlist(["hat","top","potter","pot","pier","ripe"]. |
|
返回顶楼 | |
发表时间:2012-02-13
做个map, key是这个单词, value是这个单词按照字母顺序排序后的新词。 然后比较这个map中value一样的归位一组。
|
|
返回顶楼 | |
发表时间:2012-02-14
最后修改:2012-02-14
groovy 代码
def input = "hat, top, potter, pot, pier, ripe" def out = [:] input.split(", ").each { def a = it.toCharArray() Arrays.sort(a) def key = new String(a) if(out.containsKey(key)) { out.put(key, out.get(key) + ", " + it) } else { out.put(key, it) } } out.values().each { println it } |
|
返回顶楼 | |
发表时间:2012-02-15
我的想法是这样的:a,b,c,...z 用1,2,4, ....2的(z-a)次方来表示.
比较两个字符串是否一样: 1. 长度一样 2. 全部字符替换成数字后累加和一样, eg: sum(ab)=1+2=3,sum(ba)=2+1=3 key = length(str)+"-"+sum(str) key一样,字符就相等. 数据结构实现 Map<String,List> List放相同单词 代码: package com.robin.question; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; public class Question1 { public static Map<String,Long> letterValueMap = new HashMap(); Question1(){ int begin = (int)'a'; int end = (int)'z'; for(int i=begin;i<=end;i++){ String str = String.valueOf((char)i); int j = i-begin; Long value = _MN(2,j); letterValueMap.put(str, value); } } public void PrintGroupsWithSameLetters (String str){ Map ret = new TreeMap<String,ArrayList>(); if(str!=null && str.length()>0){ String arr [] = str.split(","); for(int i=0;i<arr.length;i++){ String s = arr[i]; Long value = calStr(s); StringBuffer key = new StringBuffer(""); key.append(s.length()); key.append("-"); key.append(value); if(ret.containsKey(key.toString())){ List strList = (List) ret.get(key.toString()); strList.add(s); }else{ List strList = new ArrayList(); strList.add(s); ret.put(key.toString(), strList); } } } output(ret); } public static void output(Map ret){ if(ret!=null && !ret.isEmpty()){ Set<String> keys = ret.keySet(); for(String key:keys){ List<String> list = (List) ret.get(key); if(list!=null && !list.isEmpty()){ for(int i=0;i<list.size();i++){ if(i>0){ System.out.print(","); } System.out.print(list.get(i).trim()); } System.out.println(); } } } } public static Long _MN(int m,int n){ Long value = 1L; while(n>0){ value = value * m; n--; } return value; } public static Long calStr(String str){ Long value = 0l; str = str.toLowerCase().trim(); char strArr[] = str.toCharArray(); for(int i=0;i<strArr.length;i++){ String s = String.valueOf(strArr[i]); value = value +letterValueMap.get(s); } return value; } public static void main(String[] args) { Question1 a = new Question1(); String str = "hat, top, potter, pot, pier, ripe"; a.PrintGroupsWithSameLetters(str); } } |
|
返回顶楼 | |
发表时间:2012-02-15
qseasideq 写道 我的想法是这样的:a,b,c,...z 用1,2,4, ....2的(z-a)次方来表示.
比较两个字符串是否一样: 1. 长度一样 2. 全部字符替换成数字后累加和一样, eg: sum(ab)=1+2=3,sum(ba)=2+1=3 key = length(str)+"-"+sum(str) key一样,字符就相等. 数据结构实现 Map<String,List> List放相同单词 代码: package com.robin.question; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; public class Question1 { public static Map<String,Long> letterValueMap = new HashMap(); Question1(){ int begin = (int)'a'; int end = (int)'z'; for(int i=begin;i<=end;i++){ String str = String.valueOf((char)i); int j = i-begin; Long value = _MN(2,j); letterValueMap.put(str, value); } } public void PrintGroupsWithSameLetters (String str){ Map ret = new TreeMap<String,ArrayList>(); if(str!=null && str.length()>0){ String arr [] = str.split(","); for(int i=0;i<arr.length;i++){ String s = arr[i]; Long value = calStr(s); StringBuffer key = new StringBuffer(""); key.append(s.length()); key.append("-"); key.append(value); if(ret.containsKey(key.toString())){ List strList = (List) ret.get(key.toString()); strList.add(s); }else{ List strList = new ArrayList(); strList.add(s); ret.put(key.toString(), strList); } } } output(ret); } public static void output(Map ret){ if(ret!=null && !ret.isEmpty()){ Set<String> keys = ret.keySet(); for(String key:keys){ List<String> list = (List) ret.get(key); if(list!=null && !list.isEmpty()){ for(int i=0;i<list.size();i++){ if(i>0){ System.out.print(","); } System.out.print(list.get(i).trim()); } System.out.println(); } } } } public static Long _MN(int m,int n){ Long value = 1L; while(n>0){ value = value * m; n--; } return value; } public static Long calStr(String str){ Long value = 0l; str = str.toLowerCase().trim(); char strArr[] = str.toCharArray(); for(int i=0;i<strArr.length;i++){ String s = String.valueOf(strArr[i]); value = value +letterValueMap.get(s); } return value; } public static void main(String[] args) { Question1 a = new Question1(); String str = "hat, top, potter, pot, pier, ripe"; a.PrintGroupsWithSameLetters(str); } } 不知道楼上验算过这个公式么 ∑j2^k≠∑j'2^k' ∑j≠∑j' |
|
返回顶楼 | |