题意
以字符串的形式给一个二进制数,对这个二进制数循环右移k位,求右移结果的十进制的值。
二进制位数小于等于63
方法
模拟
按照题意,我们操作字符串k次,每次移动一位,63次后得到了目标的二进制表示的字符串
再对二进制字符串进行转化成10进制,需要注意的是这里是long long 不是int
代码
class Solution {
public:
    /**
     * 位移后二进制串的十进制值
     * @param str string字符串 二进制字符串
     * @param k int整型 循环位移次数
     * @return long长整型
     */
    long long rotateRight(string str, int k) {
        for(int i = 0;i<k;i++){
            char ch = str[str.length()-1];
            str = ch+str;
            str.pop_back();
        }
        long long res = 0;
        for(int i = 0;i<str.length();i++){
            res*=2;
            res+= str[i]-'0';
        }
        return res;
    }
};
 复杂度分析
时间复杂度:
我们首先操作字符串k次, 每次将字符串最后一位移动到最前,时间复杂度为 O(k)
然后是进制转换,对每一位进行操作一次所以复杂度是O(len(str)),综上 总时间时间复杂度为O(k+len(str))
空间复杂度: 只用了常数大小的额外空间来记录结果和做for循环,所以空间复杂度为O(1)
抽象优化
如果我们需要算1到n的和,我们并不需要循环从1到n,而是可以直接求和公式,同样,虽然说题目描述是循环右移,那么可以看一下当前位置与实际位置的区别,从意义上完成一个等效的操作,而不去实际操作它
以样例数据为例
| - | 1 | 0 | 1 | 1 | 0 | 
|---|---|---|---|---|---|
| 实际位置 | 2 | 3 | 4 | 0 | 1 | 
| 当前位置 | 0 | 1 | 2 | 3 | 4 | 
| 当前位置 | 2-2 | 3-2 | 4-2 | 5+0-2 | 5+1-2 | 
| 实际位置 | 当前位置 | 
|---|---|
| i(i>=k) | i−k | 
| i(i<k) | len(str)+i−k | 
这样的位置可以用取模汇总成一个表达式
| 实际位置 | 当前位置 | 
|---|---|
| i | (len(str)+i−k)modlen(str) | 
令 f(i)=(len(str)+i−k)modlen(str), f(实际位置)=当前位置
因此原来的进制转换是s[0 ~ len(str)-1],现在变成s[f(0) ~ f(len(str)-1)]
代码
class Solution {
public:
    /**
     * 位移后二进制串的十进制值
     * @param str string字符串 二进制字符串
     * @param k int整型 循环位移次数
     * @return long长整型
     */
    long long rotateRight(string str, int k) {
        long long res = 0;
        for(int i = 0;i<str.length();i++){
            res*=2;
            res+= str[((int)str.length()-k+i)%str.length()]-'0';
        }
        return res;
    }
};
 复杂度分析
时间复杂度: 我们省去了字符串的操作步骤,直接转换,每一位一次运算,以时间复杂度是O(len(str))
空间复杂度: 只用了常数大小的额外空间来记录结果和做for循环,所以空间复杂度为O(1)

京公网安备 11010502036488号