题目描述:
   给定一个字符串和要旋转的次数/位数, 请给出左旋之后的字符串;
   比如:输入:"abcXXzDEF", 3
             输出: "XXzDEFabc"

所谓左旋,是将串最左边的值,逆时针旋转到最右边; 
所谓右旋,是将串最右边的值,顺时针旋转到最左边;
实现思路:
    看了好几种实现方式,觉得下面这种思路是最容易理解的,学习后,记录下来:
     1、我们会发现对于上面长度为9个字符串,左旋一次后结果是: bcXXzDEFa ;  左旋两次后的结果是: cXXzDEFab ;依次类推,左旋9次后:又变成了abcXXzDEF;
           所以,我们理解,旋转9次的结果,同旋转0次的结果一样;而旋转10次的结果,同旋转1次的结果一样; 所有有: 旋转n次的结果,同旋转 n%len(s) 的结果是一样的;
     2、我们发现,对字符串 abcXXzDEF  左旋多少次,其结果都是 『abcXXzDEFabcXXzDEF』的子串,也就是将串拼接起来;  
           此时,左旋一次,就表示对拼接后的串,从第1位(默认从第0位开始)开始取,取长度为len(s);   由上面分析,那么左旋10次的结果通过旋转1次的结果一样; 
           所以,旋转n次的结果,就是从第n%len(s) 开始取, 取len(s)长度的子串,返回即可;

代码实现:
class Soution:
    def LeftRoateString(self, s, n):
        # 首先依然是,先对异常情况的处理
        if (s == ""):
            return ""
        else:
            len_s = len(s)
            s = s + s
            n = n % len_s
            return s[n:n+len_s]
扩展学习:
1、如果是右旋,应该怎么实现呢?
     思路: 同样的道理,左旋是将最左边的字符放到最右边; 右旋则是将最右边的串依次放到最左边; 同样的逻辑,将两个串拼接起来,旋转n次同旋转n%len(s)次结果一样;  与左旋不同的是,输出的子串不同; 
比如,串"abcXXzDEF",右旋3位,期待结果为『DEFabcXXz』; 拼接之后是『abcXXzDEFabcXXzDEF』,那么想要输出预知的子串,就需要从总串中,从正数第6(9-3)开始  输出 输出长度为9;
也就是下面的,从 『len_s - n 』(9-3)开始输出,输出长度为len_s,  那么就是 输出到『len_s - n + len_s 』
class Solution:
    def RightRoateString(self, s, n):
        if (s == ""):
            return ""
        else:
            len_s = len(s)
            s = s + s
            return s[len_s-n:len_s-n+len_s]
2、Python的切片操作:
        使用Python解决问题时,经常会遇到从某个对象中抽取特定部分的需求,而切片操作就是专门实现这一目标的有利武器;切片操作的基本使用语法是:
object[start_index:end_index:step]
1)object:是可以进行切片操作的数据类型,常用的 list(列表)、tuple(元组)、string(字符串)等可以迭代的对象,都可以进行切片操作; 
          而且,切片操作后返回的结果与切片对象类型一致;
2)step: 正负值均可,该值的绝对值表示切片的步长; 
      正值表示从左到右取值,步长为|step|;  
      负值表示从右到左取值,步长也为|step|; 
      如果没有注明该值,默认为1;
3)start_index:表示切片开始的索引; 
      如果step为正值,则start_index从左边为起点,统计的值包括该索引本身,也就是 <= start_index;默认从0开始; 
      如果step为负值,则start_index从右边为起点,统计的值包括该索引本身,也就是 <= start_index; 默认从-1开始;
4)end_index: 表示切片的结束索引;具体终点在左边还是右边,由step决定; 这里的统计的值不包括该索引本身,也就是 > end_index;
5)所以,可以理解切片的结果 应该是 >=start_index  and  < end_index
6)处理逻辑为:先看step,确定方向,再看start_index 确定起点,最后看end_index 确定终点;
7)如果切片返回的结果为非空的可切片对象,则支持连续切片操作;  
下面是举例子:
对列表的切片举例,定义 list_a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1、print list_a[2:5:1]  
    输出结果为:[2,3,4]   
    理解: 正向取值,step为1; 从下标为2的位置开始(包括下标为2的值),取值到 下标为5的位置结束(不包括下标为5的值);

2、start_index 和end_index缺失,只有step时:
      如果start_index缺失,默认从0 或者 -1 开始; 如果end_index缺失,默认到列表的最后一个,或者第一个;
   1)print list_a[::2]
      输出结果为:[0, 2, 4, 6, 8]
      理解:正向取值,step为2; 开始下标和结束下标都为空,则选取默认值, 从0开始,到列表最后;所以,上述切片操作的就是获取列表中所有偶数;
   2) print list_a[::-2]
      输出结果为: [9, 7, 5, 3, 1]
      理解: 反向取值,step为2, 开始下标和结束下标都为空,则选取默认值,从-1开始,到列表的最开始位置; 所以,上述切片操作就是逆向输出列表中所有的奇数;
   3)print list_a[:6:-2]
      输出结果为:[9,7]
      理解: 反向取值,step 为2; 开始下标缺失,默认是-1; 结束下标是6(但是取值不包括6);所以取值范围是[7,8,9],从9开始step为2,也就是[9,7]
   4)print list_a[5::-2]
      输出结果为:【5, 3, 1】
      理解: 反向取值,step 为2;  开始下标位5(取值包括该5); 结束下标缺失,默认到列表的最后一个,因为是反向取值的最后一个,所以是列表的起点位置; 
            所以,取值范围是[0,1,2,3,4,5] 从5开始step 是2,也就是[5,3,1]

3、切取单个值:
   print list_a[6]    
   输出结果为:6
   理解: 没有:的情况下,默认按照下标开始取值;下标从0开始,从左到右;

4、一些错误的使用:
   1)print list_a[1:6:-1]
      输出结果为:[]
      理解: step 为-1,表示反向取值; 但是start_index=1, end_index=6 又表示正向取值,两者矛盾,所以输出为空;
   2)print list_a[-1:-6:1]
      输出结果为:step 为 1,表示正向取值; 但是start_index=-1,end_index=-6,又表示从右到左反向取值,两者矛盾,所以输出结果为空;
对字符串的切片举例:
  对字符串的切片操作语法同上面一样,这里只是给一个字符串切片的例子;
  题目:给定一个字符串,将其首字母改为大写后返回;
  比如: 输入:hello; 输出:Hello;
Class Soultion:
    def func(self, s):
        if (s == ""):
            return ""
        else:
            return s[0].upper() + s[1:]

test = Soultion()
s = input("请输入一个单词: ")
print("转换后的单词是:" + test.func(s))