经典算法面试题目-判断s2是否是s1的旋转字符串(1.8)

题目

Assume you have a method isSubstring which checks if one word is a substring of another. Given two strings, s1 and s2, write code to check if s2 is a rotation of s1 using only one call to isSubstring ( i.e., “waterbottle” is a rotation of “erbottlewat”).

假设你有一个isSubstring函数,可以检测一个字符串是否是另一个字符串的子串。 给出字符串s1和s2,只使用一次isSubstring就能判断s2是否是s1的旋转字符串, 请写出代码。
例如:”waterbottle”是”erbottlewat”的旋转字符串。

解答

题目说我们使用一次isSubstring函数就可以判断s2是否是s1的旋转字符串, 如果从原始字符串s1和s2直接入手肯定不行,因为它们根本不存在子串关系。 如果不断地旋转字符,然后调用isSubstring,又需要调用多次的isSubstring。 而且通过旋转字符再判断,可以直接用等号判断,根本用不上isSubstring。

既然如此,我们就要考虑去改变原始字符串。要判断a串是否是b串的子串, 一般情况下都会有b串长度大于a串,长度相等的话就直接判断它们是不是相等的串了。 我们可以考虑把串s1变长,然后调用一次isSubstring判断s2是否是s1变长后的子串, 如果是,就得出s2是s1的旋转字符串。s1怎么变长呢?无非就是s1+s1或是s1+s2, s2一定是s1+s2的子串,因此这样做没有任何意义。而s1+s1呢? 我们就上面的例子进行讨论:s1=waterbottle,s2=erbottlewat. 则:

s1 + s1 = waterbottlewaterbottle

很容易可以发现,s1+s1其实是把s1中每个字符都旋转了一遍,而同时保持原字符不动。 比如waterbottle向右旋转2个字条应该是:terbottlewa,但如果同时保持原字符不动, 我们得到的就是waterbottlewa,而terbottlewa一定是waterbottlewa的子串, 因为waterbottlewa只是在terbottlewa的基础上再加上一条原字符不动的限制。 因此s1+s1将包含s1的所有旋转字符串,如果s2是s1+s1的子串,自然也就是s1 的旋转字符串了。

首先,我们来了解一个函数:
a.find(b) 表示查找字符串a是否包含子串b,若查找成功,返回按查找规则找到的第一个字符或子串的位置;若查找失败,返回npos,即-1(打印出来为4294967295)。

接下来,利用这个函数,我们可以很方便的写出判断s2是否是s1的旋转字符串的代码。

关键代码:

//判断s2是不是s1的子串
bool isSubstring(string s1, string s2){
    if(s1.find(s2) != string::npos) return true;
    else return false;
}

//防范一下,以及调用:isSubstring(s1+s1, s2)
bool isRotation(string s1, string s2){
    if(s1.length() != s2.length() || s1.length()<=0)
        return false;
    return isSubstring(s1+s1, s2);
}

完整代码:

#include <iostream>
#include <string>
using namespace std;

bool isSubstring(string s1, string s2){
    //a.find(b)查找字符串a是否包含子串b。string::npos(很大的无符号整数)也可以认为就是-1。
    if(s1.find(s2) != string::npos) return true;
    else return false;
}
bool isRotation(string s1, string s2){
    //防范一下!如果s2的长度和s1的不相等,肯定就不可能s2是s1的旋转子串了。
    if(s1.length() != s2.length() || s1.length()<=0)
        return false;
    return isSubstring(s1+s1, s2);
}

int main(){
    string s1 = "apple";
    string s2 = "pleap";
    if(isRotation(s1, s2)){
        cout<<s2+"是"+s1+"的旋转字符串"<<<<endl;
    }
    //cout<<string::npos<<endl; //4294967295
    //cout<<s1.find(s2)<<endl;  //4294967295
    return 0;
}
时间: 2024-09-20 05:48:50

经典算法面试题目-判断s2是否是s1的旋转字符串(1.8)的相关文章

经典算法面试题目-判断一个字符串中的字符是否唯一(1.1)

题目: Implement an algorithm to determine if a string has all unique characters. What if you can not use additional data structures? 实现一个算法来判断一个字符串中的字符是否唯一(即没有重复).不能使用额外的数据结构. (即只使用基本的数据结构) 解答: 首先,你可以问面试官,构成字符串的字符集有多大?是ASCII字符,还是只是26个字母? 还是有更大的字符集,对于不同

经典算法面试题目-判断两个字符串是否是变位词(1.4)

题目 Write a method to decide if two strings are anagrams or not. 写一个函数判断两个字符串是否是变位词. 解答 变位词(anagrams)指的是组成两个单词的字符相同,但位置不同的单词. 比如说, abbcd和abcdb就是一对变位词. 也就是说,2个字符串,不管排列顺序如何,只要全部的单个字符能对应上,就是一对变位词! 该题目有两种做法: 时间复杂度为O(nlogn)的解法 由于组成变位词的字符是一模一样的,所以按照字典序排序后,两

经典算法面试题目-设计算法移除字符串中重复的字符(1.3)

题目 Design an algorithm and write code to remove the duplicate characters in a string without using any additional buffer. NOTE: One or two additional variables are fine. An extra copy of the array is not. FOLLOW UP Write the test cases for this metho

经典算法面试题目-置矩阵行列元素为0(1.7)

题目 Write an algorithm such that if an element in an MxN matrix is 0, its entire row and column is set to 0. 写一个函数处理一个MxN的矩阵,如果矩阵中某个元素为0,那么把它所在的行和列都置为0. 解答 简单题.遍历一次矩阵,当遇到元素等于0时,记录下这个元素对应的行和列. 可以开一个行数组row和列数组col,当元素a[i][j]等于0时, 就把row[i]和col[j]置为1. 第二次遍

经典算法面试题目-矩阵旋转90度(1.6)

题目 Given an image represented by an NxN matrix, where each pixel in the image is 4 bytes, write a method to rotate the image by 90 degrees. Can you do this in place? 一张图像表示成NxN的矩阵,图像中每个像素是4个字节,写一个函数把图像旋转90度. 你能原地进行操作吗?(即不开辟额外的存储空间) 解答 我们假设要将图像逆时针旋转90

经典算法面试题目-翻转一个C风格的字符串(1.2)

题目: Write code to reverse a C-Style String. (C-String means that "abcd" is represented as five characters, including the null character.) 写代码翻转一个C风格的字符串.(C风格的意思是"abcd"需要用5个字符来表示,包含末尾的 结束字符) 解答: 这道题如果就是要考察你有没有注意到C风格字符串最后的那个结束符,那我觉得还是像书

几个面试经典算法题Java解答

题目一: public class testClockwiseOutput {      //顺时针打印一个矩阵           @Test      public void test(){          int[][] num = new int[100][100];          int n = 4;          int count =1;                   for(int i=0;i<n;i++){              for(int j =0;j

经典算法(12) 数组中只出现1次的两个数字(百度面试题)

首先来看题目要求: 在一个数组中除两个数字只出现1次外,其它数字都出现了2次, 要求尽快找 出这两个数字. 考虑下这个题目的简化版--数组中除一个数字只出现1次外,其它数字都成对出现 ,要求尽快找出这个数字.这个题目在之前的<位操作基础篇之位操作全面总结>中的"位操作趣味应用" 中就已经给出解答了.根据异或运算的特点,直接异或一次就可以找出这个数字. 现在数组中有两个 数字只出现1次,直接异或一次只能得到这两个数字的异或结果,但光从这个结果肯定无法得到这个两个数字 .因此我

经典算法(11) 一道有趣的GOOGLE面试题 --【解法2】

上一篇<白话经典算法系列之十一道有趣的GOOGLE面试题>中对一道有趣的GOOGLE面试题进行了详细的讲 解,使用了类似于基数排序的做法在O(N)的时间复杂度和O(1)的空间复杂度完成了题目的要求,文章发表后 ,网友fengchaokobe在评论中给出了另一种解法,见下图. 文字版: int Repeat(int *a, int n) { for(int i = 0; i < n; i++) { if(a[i] > 0) //判断条件 { if(a[ a[i] ] < 0)