检查两个字符串是否相互旋转等同。

4

我需要你的帮助来完成以下内容:我正在尝试开发一个函数,用于检查两个参数字符串是否彼此旋转相等,比如"abcd"如果我们将其顺时针旋转两次,则变成"cdab",因此我的函数应该在提供上述字符串作为参数时返回"true"。我最初解决这个问题的想法是检查两个字符串中每个字符之间的常量偏移是否存在,因此我尝试了:

function areRotEq (str1, str2) {
    var shift = null;
    for(char of str1){
        if(!shift) shift = str2.indexOf(char);
        else if (shift != str2.indexOf(char)) return false
    }
    return true;
}

但是,它甚至不能正确地评估上述简单字符串,并返回“false”。如果您可以指导我找出为什么我的代码不起作用,或者提供一些更有效的解决方法来解决我的问题,那将不胜感激。 提前致谢!

8个回答

4

以下是一种替代方法:

首先,进行绝对真或假的“快速”检查。

然后,在str2中检查str1的第一个字符。在此处分割它,并将第一部分粘贴到最后面。如果两者相等,则它们是旋转的。

警告:对于包含同一字符多次的字符串,此方法不适用。

function areRotEq (str1, str2) {
    if (str1 === str2) return true;
    if (str1.length !== str2.length) return false;
    
    var start2 = str2.indexOf(str1[0]);
    if (start2 === -1) return false;

    return str1 === str2.slice(start2) + str2.slice(0, start2)
}

console.log(
  areRotEq("abcd", "abcd"),
  areRotEq("abcd", "acdb"),
  areRotEq("abcd", "dabc"),
  areRotEq("dcab", "abdc")
);


好的发现。谢谢您的评论。我会加一个快速警告,可惜现在没有时间修复。 - user3297291

2

这是我解决这个问题的方法。我会不断地移动str1,直到它与str2匹配,或者尝试了每种移动组合。

原始答案:Original Answer

function areRotEq (str1, str2) {
    for(let i=0; i<str1.length; ++i) {
        // shift str1
        str1 = str1[str1.length-1] + str1.substring(0, str1.length-1);
        if(str1 === str2) {
            return true;
        }
    }
    return false;
}


console.log(
    areRotEq('12345', '34512'), // true
    areRotEq('12345', '23451'), // true
    areRotEq('12345', '12354') // false
);

1
如果两个字符串是彼此旋转的,那么一个字符串存在于另一个字符串中,并且连续重复两次!实现这个逻辑非常容易:

function rotEq(str1, str2) {
  var str = str1 + str1;
  return str.includes(str2);
}

console.log(rotEq("abcd", "bcda"));
console.log(rotEq("abcde", "cdeab"));
console.log(rotEq("abcd", "acdb"));


1

你的解决方案无法正常工作,因为你错误地计算了偏移量,以下是你可以修复它的方法:

function areRotEq (str1, str2) {
    var shift = null;
    let i = 0;
    for(char of str1){
        if(!shift) shift = str2.indexOf(char);
        else {
            const currentShift = Math.abs(str2.indexOf(char) - i);
            if (shift != currentShift) return false;
        } 
        i++;
    }
    return true;
}

这里是连接技巧的解决方案:

function areRotEq (str1, str2) {
    if (str1.length != str2.length) return false;
    return (str1 + str1).indexOf(str2) != -1;
}

1
那个连接技巧将会对areRotEq('abcd','abc')返回true - Yevhen Horbunkov
你是对的,需要额外检查字符串长度是否相等。 - Alex
1
我更喜欢ES6版本的代码:const areRotEq = (str1, str2) => str1.length == str2.length && str1.repeat(2).indexOf(str2) > -1 - Yevhen Horbunkov
那个 concat 的东西似乎比其他解决方案表现要好,而且根据 @U25lYWt5IEJhc3RhcmQg 的建议,这也是最紧凑的解决方案,所以我接受了那个。谢谢! - s_tyagi

0
我会使用findIndex来处理具有多个字母重复的字符串并将其删除。
function areRotEq(str1, str2) {
    const str1Array = str1.split('');
    const str2Array = str2.split('');
    for (let i = str1Array.length - 1; i >= 0 ; i--) {
        const index = str2Array.findIndex(letter => letter === str1Array[i]);
        if (index === -1) {
            return false;
        }
        str2Array.splice(index, 1);
    }
    return str2Array.length === 0;
}
console.log(areRotEq('abcda', 'cdaba'));

0

您可以将字符串表示为一个牌组结构,即字符的牌组(能够在集合的开头和末尾放置元素,就像一副扑克牌)。非常方便的是,JavaScript数组提供了此功能(通过队列和堆栈方法shiftpush)。基本上,我们取出字符串中的第一个字符,并将其移动到最后一个位置,然后进行新的相等性检查。我们重复此操作,直到字符串被移动(或旋转)到其初始值:

function areRotEq(str1, str2) {
    if (str1.length !== str2.length) {
        return false;
    }

    if (str1 === str2) {
        return true;
    }

    let str1Array = str1.split('');
    let tempEl;

    for (let i = 0; i < str1.length - 1; i++) {
        tempEl = str1Array.shift();
        str1Array.push(tempEl);

        if (str1Array.join('') === str2) {
            return true;
        }
    }

    return false;
}

0
你可以使用 for 循环,从 0 开始递增第一个字符串的索引,并从第二个字符串的长度开始递减其索引。通过这两个索引,你可以比较字符串中特定的字符。

function areRotEq(str1, str2) {
  for (var a = 0; a < str1.length; a++) {
    if (str1.charAt(a) != str2.charAt(str2.length - (a + 1))) {
      return false;
    }
  }
  return true;
}
console.log(areRotEq("abcd", "dcba"));


1
当重复字符出现时,此代码将失败(例如对于'aabc'、'abca'它将返回“false”)。 - Yevhen Horbunkov

0

这个函数将检查两个字符串是否在旋转意义下相等,如果两个字符串在旋转意义下相等,则返回使它们相等所需的旋转元素数量。

const areRotEq= (first, second) => {
  let result = -1;
  const lengthUnmatch = first.length != second.length
  if (lengthUnmatch)
    return result
  else
   const temp = second.concat(second)
    if (temp.includes(first))
        return temp.indexOf(first) 
    else
        return result 
 }

这个函数将检查两个字符串是否在旋转意义下相等,如果两个字符串在旋转意义下相等,则返回 true,否则返回 false。

const areRotEq= (first, second) => {
  let result = false;
  const lengthUnmatch = first.length != second.length
  if (lengthUnmatch)
    return result
  else
   const temp = second.concat(second)
    if (temp.includes(first))
        return true 
    else
        return result 
 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接