如何确定两个字符串是否是彼此的排列
答案 0 :(得分:41)
修改强>
上述方法相当有效--O(n * log(n)),并且正如其他人所示,使用标准Java API非常容易实现。更有效(但也更多的工作)是计算和比较每个字符的出现次数,使用char值作为计数数组的索引。
我不认为有一种有效的方法可以递归地进行。一种低效的方式(O(n ^ 2),如果直接实施则更糟)是:
答案 1 :(得分:29)
将@Michael Borgwardt的话放入代码:
public boolean checkAnagram(String str1, String str2) {
if (str1.length() != str2.length())
return false;
char[] a = str1.toCharArray();
char[] b = str2.toCharArray();
Arrays.sort(a);
Arrays.sort(b);
return Arrays.equals(a, b);
}
答案 2 :(得分:18)
创建一个Hashmap,其中第一个字符串的字符为键,出现次数为value;然后遍历第二个字符串,对于每个字符,查找哈希表并减少数字,如果它大于零。如果找不到条目或条目已经为0,则字符串不是彼此的排列。显然,字符串必须具有相同的长度。
答案 3 :(得分:6)
HashMap中的线性时间解决方案。遍历并在HashMap中放置第一个String,保留每个字符的计数。遍历第二个String,如果它已经在hashmap中,则将计数减少1.最后,如果所有字符都在字符串中,则hashmap中的值对于每个字符将为0。
public class StringPermutationofEachOther {
public static void main(String[] args)
{
String s1= "abc";
String s2 ="bbb";
System.out.println(perm(s1,s2));
}
public static boolean perm(String s1, String s2)
{ HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int count =1;
if(s1.length()!=s2.length())
{
return false;
}
for(Character c: s1.toCharArray())
{
if(!map.containsKey(c))
map.put(c, count);
else
map.put(c, count+1);
}
for(Character c: s2.toCharArray())
{
if(!map.containsKey(c))
return false;
else
map.put(c, count-1);
}
for(Character c: map.keySet())
{
if(map.get(c)!=0)
return false;
}
return true;
}
}
答案 4 :(得分:4)
你可以尝试使用XOR,如果一个字符串是另一个字符串的渗透,它们应该具有基本相同的字符。唯一的区别就是字符的顺序。因此,使用XOR技巧可以帮助您摆脱顺序,只关注字符。
public static boolean isPermutation(String s1, String s2){
if (s1.length() != s2.length()) return false;
int checker = 0;
for(int i = 0; i < s1.length();i++ ){
checker ^= s1.charAt(i) ^ s2.charAt(i);
}
return checker == 0;
}
答案 5 :(得分:3)
答案 6 :(得分:2)
答案 7 :(得分:2)
首先检查长度(n
),如果它们不相同,则它们不能相互排列。现在创建两个HashMap<Character, Integer>
。迭代每个字符串并将每个字符出现在字符串中的次数。例如。如果字符串是aaaaa,则地图将只有一个元素,其中键a和值为5.现在检查两个映射是否相同。这是O(n)
算法。
使用代码段进行编辑:
boolean checkPermutation(String str1, String str2) {
char[] chars1 = str1.toCharArray();
char[] chars2 = str2.toCharArray();
Map<Character, Integer> map1 = new HashMap<Character, Integer>();
Map<Character, Integer> map2 = new HashMap<Character, Integer>();
for (char c : chars1) {
int occ = 1;
if (map1.containsKey(c) {
occ = map1.get(c);
occ++;
}
map1.put(c, occ);
}
// now do the same for chars2 and map2
if (map1.size() != map2.size()) {
return false;
}
for (char c : map1.keySet()) {
if (!map2.containsKey(c) || map1.get(c) != map2.get(c)) {
return false;
}
}
return true;
}
答案 8 :(得分:1)
其他方法的变化,但是这个方法使用2个int数组来跟踪字符,没有排序,你只需要在字符串上循环1。我在int数组上做的for循环测试置换是一个常量,因此不是N的一部分。
记忆力不变。
O(N)运行时间。
// run time N, no sorting, assume 256 ASCII char set
public static boolean isPermutation(String v1, String v2) {
int length1 = v1.length();
int length2 = v2.length();
if (length1 != length2)
return false;
int s1[] = new int[256];
int s2[] = new int[256];
for (int i = 0; i < length1; ++i) {
int charValue1 = v1.charAt(i);
int charValue2 = v2.charAt(i);
++s1[charValue1];
++s2[charValue2];
}
for (int i = 0; i < s1.length; ++i) {
if (s1[i] != s2[i])
return false;
}
return true;
}
}
单元测试
@Test
public void testIsPermutation_Not() {
assertFalse(Question3.isPermutation("abc", "bbb"));
}
@Test
public void testIsPermutation_Yes() {
assertTrue(Question3.isPermutation("abc", "cba"));
assertTrue(Question3.isPermutation("abcabcabcabc", "cbacbacbacba"));
}
答案 9 :(得分:1)
如果我们进行初始长度检查,以确定两个字符串是否具有相同的长度,
public boolean checkIfPermutation(String str1, String str2) {
if(str1.length()!=str2.length()){
return false;
}
int str1_sum = getSumOfChars(str1);
int str2_sum = getSumOfChars(str2);
if (str1_sum == str2_sum) {
return true;
}
return false;
}
public int getSumOfChars(String str){
int sum = 0;
for (int i = 0; i < str.length(); i++) {
sum += str.charAt(i);
}
return sum;
}
答案 10 :(得分:1)
public boolean isPermutationOfOther(String str, String other){
if(str == null || other == null)
return false;
if(str.length() != other.length())
return false;
Map<Character, Integer> characterCount = new HashMap<Character, Integer>();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
int count = 1;
if(characterCount.containsKey(c)){
int k = characterCount.get(c);
count = count+k;
}
characterCount.put(c, count);
}
for (int i = 0; i < other.length(); i++) {
char c = other.charAt(i);
if(!characterCount.containsKey(c)){
return false;
}
int count = characterCount.get(c);
if(count == 1){
characterCount.remove(c);
}else{
characterCount.put(c, --count);
}
}
return characterCount.isEmpty();
}
答案 11 :(得分:1)
我做到了这一点,而且效果很好而且很快:
public static boolean isPermutation(String str1, String str2)
{
char[] x = str1.toCharArray();
char[] y = str2.toCharArray();
Arrays.sort(x);
Arrays.sort(y);
if(Arrays.equals(x, y))
return true;
return false;
}
答案 12 :(得分:0)
public static boolean isPermutation(String s1, String s2) {
if (s1.length() != s2.length()) {
return false;
}else if(s1.length()==0 ){
return true;
}
else if(s1.length()==1){
return s1.equals(s2);
}
char[] s = s1.toCharArray();
char[] t = s2.toCharArray();
for (int i = 0; i < s.length; i++) {
for (int j = 0; j < t.length; j++) {
if (s.length == s1.length() && (i == 0 && j == t.length - 1) && s[i] != t[j]) {
return false;
}
if (s[i] == t[j]) {
String ss = new String(s);
String tt = new String(t);
s = (ss.substring(0, i) + ss.substring(i + 1, s.length)).toCharArray();
t = (tt.substring(0, j) + tt.substring(j + 1, t.length)).toCharArray();
System.out.println(new String(s));
System.out.println(new String(t));
i = 0;
j = 0;
}
}
}
return s[0]==t[0] ;
}
此解决方案适用于任何字符集。具有O(n)复杂度。
输出:isPermutation("The Big Bang Theory", "B B T Tehgiangyroeh")
he Big Bang Theory
B B Tehgiangyroeh
e Big Bang Theory
B B Tegiangyroeh
Big Bang Theory
B B Tgiangyroeh
Big Bang Theory
BB Tgiangyroeh
ig Bang Theory
B Tgiangyroeh
g Bang Theory
B Tgangyroeh
Bang Theory
B Tangyroeh
Bang Theory
B Tangyroeh
Bng Theory
B Tngyroeh
Bg Theory
B Tgyroeh
B Theory
B Tyroeh
BTheory
BTyroeh
Bheory
Byroeh
Beory
Byroe
Bory
Byro
Bry
Byr
By
By
B
B
true
答案 13 :(得分:0)
class Solution {
public boolean checkInclusion(String s1, String s2) {
int[] map = new int[128];
for (char c : s1.toCharArray()) {
map[c]++;
}
int count = s1.length();
char[] chars = s2.toCharArray();
int left = 0, right = 0;
while (right < chars.length) {
if (map[chars[right++]]-- > 0) count--;
while (count == 0) {
if (right - left == s1.length()) return true;
if (++map[chars[left++]] > 0) count++;
}
}
return false;
}
}
答案 14 :(得分:0)
使用XOR的属性(标识,可交换和自反)。复杂度:O(N)
,编程语言C#
static bool IsPerm(string word, string targetWord){
if(word.Length != targetWord.Length){
return false;
}
var xorProduct = 0;
for(var i = 0; i < word.Length; i++){ // O(N)
xorProduct ^= word[i] ^ targetWord[i];
}
return xorProduct == 0;
}
答案 15 :(得分:0)
时间复杂度:O(n)
public static boolean isPermutation(String str1, String str2) {
if (str1.length() != str2.length()) {
return false;
}
for (int i = 0; i < str1.length(); i++) {
char ch = str1.charAt(i);
if (str2.indexOf(ch) == -1)
return false;
else
str2 = str2.replaceFirst(String.valueOf(ch), " ");
}
return true;
}
TestCase
@Test
public void testIsPernutationTrue() {
assertTrue(Permutation.isPermutation("abc", "cba"));
assertTrue(Permutation.isPermutation("geeksforgeeks", "forgeeksgeeks"));
assertTrue(Permutation.isPermutation("anagram", "margana"));
}
@Test
public void testIsPernutationFalse() {
assertFalse(Permutation.isPermutation("abc", "caa"));
assertFalse(Permutation.isPermutation("anagramm", "marganaa"));
}
答案 16 :(得分:0)
我正在开发一个可以简化任务的Java库。您只需使用两个方法调用re-implement this algorithm即可:
boolean arePermutationsOfSameString(String s1, String s2) {
s1 = $(s1).sort().join();
s2 = $(s2).sort().join();
return s1.equals(s2);
}
@Test
public void stringPermutationCheck() {
// true cases
assertThat(arePermutationsOfSameString("abc", "acb"), is(true));
assertThat(arePermutationsOfSameString("bac", "bca"), is(true));
assertThat(arePermutationsOfSameString("cab", "cba"), is(true));
// false cases
assertThat(arePermutationsOfSameString("cab", "acba"), is(false));
assertThat(arePermutationsOfSameString("cab", "acbb"), is(false));
// corner cases
assertThat(arePermutationsOfSameString("", ""), is(true));
assertThat(arePermutationsOfSameString("", null), is(true));
assertThat(arePermutationsOfSameString(null, ""), is(true));
assertThat(arePermutationsOfSameString(null, null), is(true));
}
如果您可以克隆souces at bitbucket。
答案 17 :(得分:0)
仅使用一个HashMap的线性时间解决方案。
public static boolean check( String string1, String string2 ){
HashMap<String, Integer> map = new HashMap<String, Integer>();
if( string1.length() != string2.length()){
return false;
}
for( int i=0; i<string1.length(); i++ ){
if( map.containsKey( String.valueOf( string1.charAt(i)))){
map.put( String.valueOf( string1.charAt(i)), map.get( String.valueOf( string1.charAt(i)) ) + 1 );
}else{
map.put( String.valueOf( string1.charAt(i)), 1 );
}
}
for( int i=0; i<string2.length(); i++ ){
if( map.containsKey( String.valueOf( string2.charAt(i)))){
map.put( String.valueOf( string2.charAt(i)), map.get( String.valueOf( string2.charAt(i))) - 1);
}else{
return false;
}
}
for(Map.Entry<String, Integer> entry: map.entrySet()){
if( entry.getValue() != 0 ){
return false;
}
}
return true;
}
答案 18 :(得分:0)
我想为这个问题提供递归解决方案,因为我没有找到任何递归的答案。我认为这段代码看起来很难,但是如果你试着理解它,你会看到这段代码的美妙之处。递归有时很难理解但很好用!此方法返回输入的String''的所有排列,并将它们保存在数组'arr []'中。 “t”的值最初为空白“”。
import java.io.*;
class permute_compare2str
{
static String[] arr= new String [1200];
static int p=0;
void permutation(String s,String t)
{
if (s.length()==0)
{
arr[p++]=t;
return;
}
for(int i=0;i<s.length();i++)
permutation(s.substring(0,i)+s.substring(i+1),t+s.charAt(i));
}
public static void main(String kr[])throws IOException
{
int flag = 0;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the first String:");
String str1 = br.readLine();
System.out.println("Enter the second String:");
String str2 = br.readLine();
new permute_compare2str().permutation(str1,"");
for(int i = 0; i < p; ++i)
{
if(arr[i].equals(str2))
{
flag = 1;
break;
}
}
if(flag == 1)
System.out.println("True");
else
{
System.out.println("False");
return;
}
}
}
我可以看到一个限制是数组的长度是固定的,因此无法返回大字符串值's'的值。请根据要求改变相同。此问题还有其他解决方案。
我已经分享了这段代码,因为您实际上可以使用它来获取直接打印的字符串的排列,而不使用数组。
下面:
void permutations(String s, String t)
{
if (s.length()==0)
{
System.out.print(t+" ");
return;
}
for(int i=0;i<s.length();i++)
permutations(s.substring(0,i)+s.substring(i+1),t+s.charAt(i));
}
's'的值是需要排列的字符串,'t'的值再次为空“”。
答案 19 :(得分:0)
bool is_permutation1(string str1, string str2) {
sort(str1.begin(), str1.end());
sort(str2.begin(), str2.end());
for (int i = 0; i < str1.length(); i++) {
if (str1[i] != str2[i]) {
return false;
}
}
return true;
}
答案 20 :(得分:0)
根据对此解决方案的评论,https://stackoverflow.com/a/31709645/697935采用了这种方法,并进行了修订。
private static boolean is_permutation(String s1, String s2) {
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int count = 1;
if(s1.length()!=s2.length()) {
return false;
}
for(Character c: s1.toCharArray()) {
if(!map.containsKey(c)) {
map.put(c, 1);
}
else {
map.put(c, map.get(c) + 1);
}
}
for(Character c: s2.toCharArray()) {
if(!map.containsKey(c)) {
return false;
}
else {
map.put(c, map.get(c) - 1);
}
}
for(Character c: map.keySet()) {
if(map.get(c) != 0) { return false; }
}
return true;
}
答案 21 :(得分:0)
这是我编写的一个简单程序,它给出了O(n)中时间复杂度和O(1)空间复杂度的答案。它的工作原理是将每个字符映射到素数,然后将字符串的主映射中的所有字符相乘。如果两个字符串是排列,那么它们应该具有相同的唯一字符,每个字符具有相同的出现次数。
以下是一些完成此操作的示例代码:
// maps keys to a corresponding unique prime
static Map<Integer, Integer> primes = generatePrimes(255); // use 255 for
// ASCII or the
// number of
// possible
// characters
public static boolean permutations(String s1, String s2) {
// both strings must be same length
if (s1.length() != s2.length())
return false;
// the corresponding primes for every char in both strings are multiplied together
int s1Product = 1;
int s2Product = 1;
for (char c : s1.toCharArray())
s1Product *= primes.get((int) c);
for (char c : s2.toCharArray())
s2Product *= primes.get((int) c);
return s1Product == s2Product;
}
private static Map<Integer, Integer> generatePrimes(int n) {
Map<Integer, Integer> primes = new HashMap<Integer, Integer>();
primes.put(0, 2);
for (int i = 2; primes.size() < n; i++) {
boolean divisible = false;
for (int v : primes.values()) {
if (i % v == 0) {
divisible = true;
break;
}
}
if (!divisible) {
primes.put(primes.size(), i);
System.out.println(i + " ");
}
}
return primes;
}
答案 22 :(得分:0)
String str= "abcd";
String str1 ="dcazb";
int count=0;
char s[]= str.toCharArray();
char s1[]= str1.toCharArray();
for(char c:s)
{
count = count+(int)c ;
}
for(char c1:s1)
{
count=count-(int)c1;
}
if(count==0)
System.out.println("String are Anagram");
else
System.out.println("String are not Anagram");
}
答案 23 :(得分:0)
最好的方法是首先对两个字符串进行排序然后进行比较。它不是最有效的方式,但它很干净,并且已经使用了分拣程序的运行时间。
boolean arePermutation(String s1, String s2) {
if(s1.lenght() != s2.lenght()) {
return false;
}
return mySort(s1).equals(mySort(s2));
}
String mySort(String s) {
Char letters[] = s.toCharArray();
Arrays.sort(letters);
return new String(letters);
}
答案 24 :(得分:0)
我是用C#
做的bool Arepermutations(string string1, string string2)
{
char[] str1 = string1.ToCharArray();
char[] str2 = string2.ToCharArray();
if (str1.Length !=str2.Length)
return false;
Array.Sort(str1);
Array.Sort(str2);
if (str1.Where((t, i) => t!= str2[i]).Any())
{
return false;
}
return true;
}
答案 25 :(得分:0)
可以通过在C#中使用Dictionary来完成。基本实现如下:
private static bool IsPermutation(string str1, string str2)
{
if (str1.Length != str2.Length)
return false;
var dictionary = new Dictionary<char, int>();
foreach(var x in str1)
{
if (dictionary.ContainsKey(x))
dictionary[x] += 1;
else
dictionary.Add(x, 1);
}
foreach (var y in str2)
{
if (dictionary.ContainsKey(y))
{
if (dictionary[y] > 0)
dictionary[y] -= 1;
else
return false;
}
else
return false;
}
foreach(var el in dictionary)
{
if (el.Value != 0)
return false;
}
return true;
}
时间复杂度是O(n),线性解。
答案 26 :(得分:0)
创建两种方法:
<强> 1。第一种方法接受一个字符串并返回一个已排序的字符串:
public String sort(String str) {
char char_set[] = str.toCharArray();
Arrays.sort(char_set);
return new String(char_set);
}
<强> 2。第二种方法需要两个字符串并返回一个布尔值:
`public boolean sort(String x, String y) {
if (x.length() != y.length()) {
System.out.println("false");
return false;
}
System.out.println(sort(x).equals(sort(y)));
return sort(x).equals(sort(y));
}`
答案 27 :(得分:0)
这是O(N)解决方案,其中N是较短字符串的长度。
它有一个缺点,即只有ASCII字符是可以接受的。
如果我们想要更好的适用性,我们可以用哈希表替换int charNums[]
。
但这也意味着C不是一个好的选择,因为它不是一个好的选择。 C没有标准的哈希表实现。
int is_permutation(char *s1, char *s2)
{
if ((NULL == s1) ||
(NULL == s2)) {
return false;
}
int static const
_capacity = 256; // Assumption
int
charNums[_capacity] = {0};
char
*cRef1 = s1,
*cRef2 = s2;
while ('\0' != *cRef1 && '\0' != *cRef2) {
charNums[*cRef1] += 1;
charNums[*cRef2] -= 1;
cRef1++;
cRef2++;
}
if ('\0' != *cRef1 || '\0' != *cRef2) {
return false;
}
for (int i = 0; i < _capacity; i++) {
if (0 != charNums[i]) {
return false;
}
}
return true;
}
答案 28 :(得分:0)
>>>def isPermutation = lambda x, y: set([i for i in x]) == set([j for j in x])
>>>isPermutation("rasp", "spar")
>>>True
答案 29 :(得分:0)
public class TwoStrgPermutation {
public int checkForUnique(String s1, String s2)
{
int[] array1 = new int[256];
int[] array2 = new int[256];
array1 = arrayStringCounter(array1,s1);
array2 = arrayStringCounter(array2,s2);
if(Arrays.equals(array1, array2))
return 0;
else
return 1;
}
public int[] arrayStringCounter(int[] array,String s)
{
int val;
for(int i=0;i<s.length();i++)
{
val = (int)s.charAt(i);
array[val]++;
}
return array;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
InputStreamReader in = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(in);
TwoStrgPermutation obj = new TwoStrgPermutation();
try {
String string1 = br.readLine();
String string2 = br.readLine();
int len1 = string1.length();
int len2 = string2.length();
if(len1==len2)
{
int result = obj.checkForUnique(string1,string2);
if (result == 0){
System.out.println("yes it is a permutation");
}
else if (result >0)
{
System.out.println("no it is not");
}
}
else
{
System.out.println("no it is not");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
答案 30 :(得分:0)
强制性Guava单行:
boolean isAnagram(String s1, String s2) {
return ImmutableMultiset.copyOf(Chars.asList(s1.toCharArray())).equals(ImmutableMultiset.copyOf(Chars.asList(s2.toCharArray())));
}
(只是为了好玩。我不建议为你的作业提交。)
答案 31 :(得分:0)
根据您的要求,这是一个使用递归的完整解决方案。 现在你所要做的就是:
proc isAnagram(s1, s2);
return {s1, s2} = {''} or
(s2 /= '' and
(exists c = s1(i) |
s2(1) = c and
isAnagram(s1(1..i-1) + s1(i+1..), s2(2..))));
end isAnagram;
答案 32 :(得分:0)
import java.io.*;
public class permute
{
public static String sort(String s)
{
char[] str = s.toCharArray();
java.util.Arrays.sort(str);
return new String(str);
}
public static boolean permutation(String s,String t)
{
if(s.length()!=t.length())
{
return false;
}
return sort(s).equals(sort(t));
}
public static void main(String[] args) throws IOException
{
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String string = null;
boolean x=true;
System.out.println("Input String:");
string = bf.readLine();
System.out.println("Input another String:");
String result = bf.readLine();
String resultant = sort(string);
if(x==permutation(result,resultant))
{
System.out.println("String"+" "+"("+result+")"+"is a permutation of String"+" "+"("+string+")");
}
else
{
System.out.println("Sorry No anagram found");
}
}
}
答案 33 :(得分:0)
public boolean permitation(String s,String t){
if(s.length() != t.length()){
return false;
}
int[] letters = new int[256];//Assumes that the character set is ASCII
char[] s_array = s.toCharArray();
for(char c:s_array){ /////count number of each char in s
letters[c]++;
}
for(int i=0;i<t.length();i++){
int c = (int)t.charAt(i);
if(--letters[c]<0){
return false;
}
}
return true;
}
答案 34 :(得分:-1)
如果有人关心,我在C中这样做了。它假定ASCII值并使用字符序数值:
bool is_permutation(const char *a, const char *b)
{
if (a == NULL || b == NULL)
return false;
if (strlen(a) != strlen(b))
return false;
int sum_a = 0, sum_b = 0;
while (*a != '\0')
sum_a += (int)*a++;
while (*b != '\0')
sum_b += (int)*b++;
return (sum_a == sum_b);
}