锁定老帖子 主题:给大家出道题,算法的
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (17)
|
|
---|---|
作者 | 正文 |
发表时间:2012-02-03
素数这个想法,来源于之前有篇老外面试的故事吧,挺不错的哈
|
|
返回顶楼 | |
发表时间:2012-02-03
//只能输入小写 public static void printGroupsWithSameLetters(String[] words) { boolean[] printed = new boolean[words.length]; int[][] value = new int[words.length][26]; for(int i=0;i<words.length;i++){ String word = words[i]; for(int j=0;j<word.length();j++){ value[i][word.charAt(j)-'a']+=1; } } for(int i=0;i<words.length;i++){ if(!printed[i]){ System.out.print(words[i]); printed[i] = true; for(int j=i+1;j<words.length;j++){ if(Arrays.toString(value[i]).equals(Arrays.toString(value[j]))){ System.out.print(" "+words[j]); printed[j] = true; } } System.out.println(); } } } |
|
返回顶楼 | |
发表时间:2012-02-03
最后修改:2012-02-03
public class CollectionTest { public static void main(String[] args) { String[] words = new String[] { "hat", "top", "potter", "pot", "pier", "ripe" }; printGroupsWithSameLetters(words); } public static void printGroupsWithSameLetters(String[] words) { List<List<Character>> wds = new ArrayList<List<Character>>(); for (String word : words) { List<Character> wd = new ArrayList<Character>(); for (char c : word.toCharArray()) { wd.add(c); } wds.add(wd); } Set<List<Character>> temp = new HashSet<List<Character>>(); List<Character> bakwd = wds.get(0); while (wds.size() > 0) { for (List<Character> wd : wds) { if (bakwd.containsAll(wd) && wd.containsAll(bakwd)) { temp.add(wd); } } printC(temp); wds.removeAll(temp); temp.clear(); if (wds.size() > 0) { bakwd = wds.get(0); } } } private static void printC(Set<List<Character>> temp) { for (List<Character> cs : temp) { StringBuffer sb = new StringBuffer(); for (Character c : cs) { sb.append(c); } System.out.print(sb + " "); } System.out.println(); } } |
|
返回顶楼 | |
发表时间:2012-02-03
最后修改:2012-02-03
//只能小写 private void PrintGroupsWithSameLetters(String[] input){ int a=(int)Math.pow(2, 25);//将a定为1000000(25个0) Map<Integer,List<String>> same=new HashMap<Integer, List<String>>(); for(String s:input){ int tmp=0; for(char c:s.toCharArray()){ tmp|=a>>(c-'a');//每个字母的26位二进制 按照a右移相应的数获得,然后或起来 } List<String> list=same.get(tmp)==null?new ArrayList<String>():same.get(tmp); list.add(s); same.put(tmp, list); } print(same); } @SuppressWarnings("rawtypes") private void print(Map map){ //按行打印,list就直接输出了,没有去掉括号 Iterator it=map.entrySet().iterator(); while(it.hasNext()){ Map.Entry entry=(Map.Entry)it.next(); System.out.println(entry.getValue()); } } } 总体思想也是 将一个字符串 映射到 hashmap里,字母相同的(比如 top pot)的hash相同 这里topper 和 potter 也定义为相同(跟题意不符,题目是with exactly the same letters,这里 not exactly) 这里hash 的方法 是 取26位的二进制数,a是100000(25个0)也就是2的25次方,b是2的24次方。。。一直到z,2的0次方,在代码里是按照a右移位数 获得,比如 b就是 a>>('b'-'a')获得 每个字符串的 字符 映射然后 按位或成 唯一的 26位 hash码,然后存到hashMap里 //input: String[] input= new String[] { "hat", "top", "potter", "pot", "pier", "ripe" }; //output: [hat] [potter] [top, pot] [pier, ripe] |
|
返回顶楼 | |
发表时间:2012-02-03
static void PrintGroupsWithSameLetters( String[] words ) { Map map = new LinkedHashMap(); for( String word : words ) { char[] charArray = word.toCharArray(); Arrays.sort( charArray ); String key = String.valueOf( charArray ); if( map.get( key ) != null ) { map.put( key, map.get( key ) + "," + word ); } else { map.put( key, word ); } } Iterator iterator = map.entrySet().iterator(); while( iterator.hasNext() ) { System.out.println( ( ( Map.Entry ) iterator.next() ).getValue() ); } } 用LinkedHashMap即可 |
|
返回顶楼 | |
发表时间:2012-02-03
我的思路与green_tea很多相同:
java实现如下: package com.xxxxxx; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map.Entry; /**** * * @author greatwqs.iteye.com * @date 2012-02-03 */ public class DivideTest { public static void main(String args[]) { String[] array = new String[] { "hat", "top", "potter", "pot", "pier", "ripe" ,"great","reatg"}; PrintGroupsWithSameLetters(array); } /*** * 采用分组的方法,首先按照字符串的长度进行分组,再针对同长度的字符串判断是否包含一样的字符! * @param words */ public static void PrintGroupsWithSameLetters(String[] words) { // Integer: 字符串的长度, ArrayList<String>: 此字符串的长度下包含的字符串List HashMap<Integer, ArrayList<String>> length2ListMap = new HashMap<Integer, ArrayList<String>>(); for (int i=0; i<words.length; i++) { int length = words[i].length(); if (!length2ListMap.containsKey(length)) { ArrayList<String> list = new ArrayList<String>(); list.add(words[i]); length2ListMap.put(new Integer(length), list); } else { ArrayList<String> list = length2ListMap.get(Integer.valueOf(length)); list.add(words[i]); } } // 字符串根据长度分组已经成功! // 下面展示length2ListMap中的元素. Iterator<Entry<Integer, ArrayList<String>>> iter = length2ListMap.entrySet().iterator(); while (iter.hasNext()) { Entry<Integer, ArrayList<String>> entry = iter.next(); ArrayList<String> list = entry.getValue(); // 如果此长度下的字符串只有一个,直接打印! if (list.size() == 1) { System.out.println(list.get(0)); } else { // 逐个进行比较 comparePrintElement(list); } } } private static void comparePrintElement(ArrayList<String> list) { // 已经打印过的下标的标记,后面用来判断此下标的值是否被打印过. String alreadyPrintIndex = ""; for (int i=0; i<list.size(); i++) { String tempString = list.get(i); // 以前没有被打印过. if (!alreadyPrintIndex.contains(String.valueOf(i))) { // 打印与此String同字符的字符串! System.out.print(tempString); alreadyPrintIndex += i + ","; char[] charArray = tempString.toCharArray(); for (int j=list.size()-1; j>i; j--) { String compareString = list.get(j); boolean flag = true; for (int k = 0; k < charArray.length; k++) { if (!compareString.contains(String.valueOf(charArray[k]))) { flag = false; } } if (flag) { System.out.print(" " + compareString); alreadyPrintIndex += j + ","; } } System.out.println(); } } } } |
|
返回顶楼 | |
发表时间:2012-02-03
最后修改:2012-02-03
判断单词中的字母:1、全部小写;2、大小写都有。
步骤: (1)将字母 减去 ASCII码中 a 或 A 对应的值作为数组的下标,初始化数组值全部为0; (2)循环单词中的每个字母,在对应数组下标值 ++,如hat中h:alphabet['h' - 97] ++; (3)循环数组下标,找出值大于0的下标值,并对下标值进行循环,拼接下标值,如top:"141519", pot:"141519"; (4)将结果放入Map中,key为"141519",value为List-top,pot。 (5)以此类推,最后打印Map。 优点:避免了对单词中的字母进行排序。 import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class GroupsWithSameLetters { public static void printGroupsWithSameLetters(String[] words, boolean lower) { Map map = null; //单词中只有小写字母 if (lower) { map = groupsWithSameLetters(words, 97, 26); } else { //单词中包含大小写 map = groupsWithSameLetters(words, 65, 58); } for(Iterator it = map.values().iterator(); it.hasNext();){ ArrayList group = (ArrayList) it.next(); StringBuffer strBuff = new StringBuffer(); for(int i = 0 ; i < group.size(); i ++){ strBuff.append(group.get(i)); strBuff.append(","); } System.out.println(strBuff.toString()); } } private static Map groupsWithSameLetters(String[] words, int value, int alphabetNum) { Map<String, ArrayList> groups = new HashMap<String, ArrayList>(); for (String word : words) { int [] alphabet = new int [alphabetNum]; for (int i = 0; i < alphabetNum; i++) { alphabet[i] = 0; } //映射字母在数组下标对应的值加1 for (char letter : word.toCharArray()) { alphabet[letter - value]++; } StringBuffer strBuff = new StringBuffer(); for (int i = 0; i < alphabetNum; i++) { if (alphabet[i] > 0) { for (int j = alphabet[i]; j > 0; j--) strBuff.append(i); } } if (groups.containsKey(strBuff.toString())) { groups.get(strBuff.toString()).add(word); } else { ArrayList result = new ArrayList(); result.add(word); groups.put(strBuff.toString(), result); } } return groups; } public static void main(String[] args) { String [] words = {"hat", "top", "potter", "pot", "pier", "ripe" }; printGroupsWithSameLetters(words, true); } } |
|
返回顶楼 | |
发表时间:2012-02-03
只考虑26个字母,全部小写
public static void main(String[] args) { printGroupsWithSameLetters("hat", "top", "potter", "pot", "pier", "ripe", "aaabc", "abbbc", "abccc"); } static void printGroupsWithSameLetters(String... words) { Map<Integer/* xor */, Map<Integer/* add */, List<String/* word */>>> map = new HashMap<Integer, Map<Integer, List<String>>>(); for (String word : words) { int[] mask = mask(word); add(map, mask, word); } for (Map<Integer/* add */, List<String/* word */>> map2 : map.values()) { for (List<String/* word */> wordList: map2.values()) { System.out.print(wordList.get(0)); for (int i = 1; i < wordList.size(); i++) { System.out.print(", "); System.out.print(wordList.get(i)); } System.out.println(); } } } static int[] mask(String word) { char[] chars = word.toCharArray(); int[] mask = new int[2]; for (char c : chars) { int x = 1 << (c - 'a'); mask[0] ^= x; mask[1] += x; } return mask; } static void add(Map<Integer/* xor */, Map<Integer/* add */, List<String/* word */>>> map, int[] mask, String word) { Map<Integer/* add */, List<String/* word */>> map2 = map.get(mask[0]); if (map2 == null) { map2 = new HashMap<Integer, List<String>>(); map.put(mask[0], map2); } List<String> wordList = map2.get(mask[1]); if (wordList == null) { wordList = new ArrayList<String>(); map2.put(mask[1], wordList); } wordList.add(word); } |
|
返回顶楼 | |
发表时间:2012-02-05
这个找个符合交换律的东西计算出一个所谓的唯一标识,并维护该标识和具体的字典
相当于做个数字签名不就搞定了吗? |
|
返回顶楼 | |
发表时间:2012-02-05
個人覺得素數的辦法仍然比較麻煩,而且計算量較大。考慮到整數是32位,只有26個字母。因此在不區分大小寫的情況下可以使用一位二進制位來標記一個字母.如果要區分大小寫,則可以考慮使用整數數組來解決。
具體的做法就是移位,移位的位數可由ASCII編碼來確定。 word_id |= 1 << (letter - 'a') 單詞ID 取或 1 向左移位 單詞中某一字母 字母a的ASCII值 這樣操作之后就可以取得整數類型的單詞ID,這個ID顯然是根據單詞當中所包括的字母確定出來的。 后面的事情就簡單了,下面給出了C的代碼。輸出的只是單詞的ID,并沒有嚴格按照樓主的形式給出輸出。 代碼如下: #include <stdio.h> #include <unistd.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <limits.h> #include <ctype.h> int main(int argc, char *argv[]) { char string[]="hat, top, potter, pot, pier, ripe"; char *p = string; int i; int j; int word[12]; int word_cnt = 0; memset( word, 0, sizeof(word) ); do { if( isalpha(*p) ) word[word_cnt] |= 1 << (*p-'a'); /* 關鍵步驟 */ if( *p == ',' ) word_cnt++; } while( *(++p) ); word_cnt++; printf( "%s\n", string ); for( i = 0; i < word_cnt; i++ ) { printf( "%d ", word[i] ); } printf( "\n" ); return 0; } 輸出結果: hat, top, potter, pot, pier, ripe 524417 573440 704528 573440 164112 164112 結果說明每個單詞已經按照字母分好了組 |
|
返回顶楼 | |