Leetcode day6:796.旋转字符串

题目描述

  1. 旋转字符串
    给定两个字符串, A 和 B。

A 的旋转操作就是将 A 最左边的字符移动到最右边。 例如, 若 A = ‘abcde’,在移动一次之后结果就是’bcdea’ 。如果在若干次旋转操作之后,A 能变成B,那么返回True。

示例 1:
输入: A = ‘abcde’, B = ‘cdeab’
输出: true

示例 2:
输入: A = ‘abcde’, B = ‘abced’
输出: false
注意:

A 和 B 长度不超过 100。

思路&代码:

最开始的思路:直接匹配,暴力遍历每一种。

class Solution {
 public boolean rotateString(String s, String goal) {
    	 if(s.length()!=goal.length())return false;
		 if(s.length()>100||goal.length()>100)return false;
		 if((s.length()==0&&goal.length()==0))return true;
    	 for(int i=0;i<s.length();i++){
             if(s.compareTo(goal)==0)return true;
             char temp = s.charAt(0);
             s=s.substring(1);
             s=s+temp;
         }
		return false;
}
}

很简单,用Java提供的字符串处理函数一个个的把字符向后移,直到找到匹配或字符串移回原样。
优化思路:

class Solution {
 public boolean rotateString(String s, String goal) {
    	if(s.length()!=goal.length())return false;
		if(s.length()>100||goal.length()>100)return false;
		if((s.length()==0&&goal.length()==0))return true;

    	int j=0;
		for(int i=s.length();i>0;i--) {
			if(s.equals(goal))return true;
			if(s.charAt(j)==goal.charAt(0)) {
				String ss = s.substring(0, j);
				s = s.substring(j);
				s += ss;
				j=0;
			}
			j++;
			
		}
		/*由于在最后缺少一次匹配,在这里补上。
		在循环里再加一次会让J越界*/
        if(s.equals(goal))return true;
    
		return false;
        
    }
}

没什么值得注意的地方,简单讲就是在字符串s中找到和goal首字母相同的字母后再对s做旋转和比较。

答案思路:

思路一

class Solution {
    public boolean rotateString(String A, String B) {
        return A.length() == B.length() && (A + A).contains(B);
    }
}

作者:LeetCode
链接:https://leetcode-cn.com/problems/rotate-string/solution/xuan-zhuan-zi-fu-chuan-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

这个比我第一种更暴力。直接将A复制一次再在AA中招子串。

思路二

class Solution {
    public boolean rotateString(String A, String B) {
        int N = A.length();
        if (N != B.length()) return false;
        if (N == 0) return true;

        //Compute shift table
        int[] shifts = new int[N+1];
        Arrays.fill(shifts, 1);
        int left = -1;
        for (int right = 0; right < N; ++right) {
            while (left >= 0 && (B.charAt(left) != B.charAt(right)))
                left -= shifts[left];
            shifts[right + 1] = right - left++;
        }

        //Find match of B in A+A
        int matchLen = 0;
        for (char c: (A+A).toCharArray()) {
            while (matchLen >= 0 && B.charAt(matchLen) != c)
                matchLen -= shifts[matchLen];
            if (++matchLen == N) return true;
        }

        return false;
    }
}

作者:LeetCode
链接:https://leetcode-cn.com/problems/rotate-string/solution/xuan-zhuan-zi-fu-chuan-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

KMP算法。不赘述。

思路三:

import java.math.BigInteger;
class Solution {
    public boolean rotateString(String A, String B) {
        if (A.equals(B)) return true;

        int MOD = 1_000_000_007;
        int P = 113;
        int Pinv = BigInteger.valueOf(P).modInverse(BigInteger.valueOf(MOD)).intValue();

        long hb = 0, power = 1;
        for (char x: B.toCharArray()) {
            hb = (hb + power * x) % MOD;
            power = power * P % MOD;
        }

        long ha = 0; power = 1;
        char[] ca = A.toCharArray();
        for (char x: ca) {
            ha = (ha + power * x) % MOD;
            power = power * P % MOD;
        }

        for (int i = 0; i < ca.length; ++i) {
            char x = ca[i];
            ha += power * x - x;
            ha %= MOD;
            ha *= Pinv;
            ha %= MOD;
            if (ha == hb && (A.substring(i+1) + A.substring(0, i+1)).equals(B))
                return true;

        }
        return false;
    }
}

作者:LeetCode
链接:https://leetcode-cn.com/problems/rotate-string/solution/xuan-zhuan-zi-fu-chuan-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

哈希算法,这个很有意思,哈希函数采用的是:hash(S) = (S[0] * P ** 0 + S[1] * P **1 + S[2] * P **2 + …) % MOD。然后计算出A和B的hash值进行比较。hash值相等则认为两串相等。感觉本质上还是暴力穷举,但是用数学减少了穷举的代价,每次旋转只需要计算:
A_newhash = (A_hash - S[0]) / P + S[0]*P **n
即可,不需要每次都对字符串进行比较。
( ** 表示次方,同^)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值