简体   繁体   中英

Check if two strings are rotationally equal to each other

I need your help with the following: I'm trying to develop a function that is supposed to check whether two argument strings are rotationally equal to each other. Like, 'abcd' would become 'cdab' if we rotate that clockwise twice, so my function is supposed to return 'true' if the above strings are supplied as arguments. My initial idea to solve this was to check whether the constant shift between each character in both strings exists, so I tried

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;
}

But, it fails to evaluate even the above simple strings properly and returns 'false'. If you could point me to the right direction to figure out why my code is not working or maybe suggest some more effective method to solve my problem that would be much appreciated. Thank you in advance!

Here's an alternative approach:

First, do the "quick" checks that are absolutely true or false.

Then, check for the first char of str1 in str2. Split it at this point and paste the first part behind the last. If the two are equal, they are rotational.

warning: this won't work for strings that contain the same character multiple times.

 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") );

This is how I solved this problem. I Basically keep shifting str1 until it matches str2, or until I've tried every shift combination.

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
);

Your solution does not work because you calculate shift incorrectly, here is how you can fix it:

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;
}

Here is concatenation trick solution:

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

If two strings are a rotation of each other, one string exists in the other string which is repeated twice continuous! Implementing of this logic is vary easy:

 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"));

You can use a for-loop and increment the index for the first string from 0 onwards and decrement the second string's index from it's length. With this two indexes you can compare the specific chars inside the string.

 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"));

i would use findIndex for strings with more then 1 occurs of letters and delete them out

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'));

You can present the string as a deck structure, namelly a deck of characters(being able to put elements in the beginning and at the end of the collection, just like a deck of cards). Pretty conveniently, the JavaScript array provides this functionality out of the box(through the queue's and stack's methods shift and push . Basically, we take out the first character in the string and move it at the last position and make a new equality check. We repeat this operation until the string get shifted(or rotated) to its initial value:

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;
}

This function will check if two strings are rotationally equal to each other and if two strings are rotationally equal then it will return number of elememts require to rotate to make them equal.

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 
 }

This function will check if two strings are rotationally equal to each other and if two strings are rotationally equal then it will return true and if not then it will return 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 
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM