第二章:Rotate、变位词

1.向量旋转

将一个具有n个元素的一维向量左旋i位。

1.1使用i个额外空间

void left_rotate(string &s,int i){
    string s2(s,0,i);//将前i个字符复制到s2
    int j=0;
    //将剩余n-i个元素左移i个位置
    for(;i<s.size();i++){
        s[j++] = s[i];
    }
    //将s2复制到s的后面部分
    for(int k=0;k<s2.size();k++){
        s[j++] = s2[k];
    }
}

1.2定义一个函数将向量左旋1位,然后i次调用该函数

//左旋一位
void one_left_rotate(string &s){
    char ch = s[0];
    for(int i=0;i<s.size()-1;i++){
        s[i] = s[i+1];
    }
    s[s.size()-1] = ch;
} 

//i次调用左旋一次函数 
void left_rotate(string &s,int i){
    for(int j=0;j<i;j++){
        one_left_rotate(s);
    }
}

1.3先转置前i位,再转置后n-i位,最后转置整个向量

void left_rotate(string &s,int i){
    reverse(s.begin(),s.begin()+i);//reverse()函数不访问后一个迭代器所指元素,需#include<algorithm>
    reverse(s.begin()+i,s.end());
    reverse(s.begin(),s.end());
}

1.4杂技算法

void left_rotate3(string &s,int rotdist){
    int n = s.size();
    int m = gcd(n,rotdist);
    for(int i=0;i<m;i++){
        int t=s[i];
        int j = i;
        while(true){
            int k = j+rotdist;
            if(k>=n){
                k -= n;
            }
            if(k==i){
                break;
            }
            s[j] = s[k];
            j = k;
        }
        s[j] = t;
    }
} 

gcd(m,n)是求m和n的最大公约数。有如下几种实现方法:

//1.辗转相除求最大公约数 ,n为0终止 
int gcd(int m,int n){//需保证m>n
    int r;
    while(n!=0){
        r = m%n;
        m = n;
        n = r;
    }
    return m;
}
//2.辗转相除的递归实现
int gcd(int m,int n){//需保证m>n
    return n==0?m:gcd(n,m%n);
}
//3.更相减损术 ,m==n终止 
int gcd(int m,int n){
    while(m!=n){
        if(m>n){
            m -= n;
        }
        else{
            n -= m;
        }
    } 
    return m;
} 

1.5块交换算法

//swap s[a..a+m-1] with s[b..b+m-1]
void swap(string &s,int a,int b,int m){
    for(int i=0;i<m;i++){
        swap(s[a+i],s[b+i]);
    }
}
//块交换算法
void left_totate(string &s,int rotdist){
    int n = s.size();
    rotdist = rotdist%n;//rotdist>=n时,只需旋转 rotdist%n位 
    if(rotdist==0){
        return;
    }
    int i = rotdist;
    int p = rotdist;
    int j = n-p;//number of elements in right
    while(i != j){
        if(i>j){
            swap(s,p-i,p,j);
            i -= j;
        }
        else{
            swap(s,p-i,p+j-i,i);
            j -= i;
        }
    } 
    swap(s,p-i,p,i);
} 

1.6STL中的rotate()

Defined in header <algorithm>
template< class ForwardIt >
void rotate( ForwardIt first, ForwardIt n_first, ForwardIt last ); (until C++11)
template< class ForwardIt >
ForwardIt rotate( ForwardIt first, ForwardIt n_first, ForwardIt last ); (since C++11)

Parameters
first    -    the beginning of the original range
n_first    -    the element that should appear at the beginning of the rotated range
last    -    the end of the original range

Return value
(none) (until C++11)
The iterator equal to first + (last - n_first) (since C++11)//point to previous first element after rotate

// simple rotation to the left
rotate(v.begin(), v.begin() + 1, v.end());
 
// simple rotation to the right
rotate(v.rbegin(), v.rbegin() + 1, v.rend());

 1.7拓展

左旋i位等价于右旋n-i位。

2.变位词

给定一本英语词典,找出所有的变位词类。

  1. 签名:按字母顺序排序单词中的字母作为签名
  2. 排序:按签名将单词排序
  3. 挤压:将签名相同的单词按行输出

#include<iostream>
#include<map>
#include<string>
#include<algorithm>

using namespace std;

int main(){
    multimap<string,string> A;
    string s,s0;
    while(cin>>s){
        s0 = s;
        sort(s.begin(),s.end());
        A.insert({s,s0});
    }
    string lastkey = A.begin()->first;
    for(auto iter=A.begin();iter != A.end();++iter){
        if(iter->first !=lastkey){
            cout<<endl;
        }
        cout<<iter->second<<ends;
        lastkey = iter->first; 
    }
    return 0;
}

3.第6题解答

  1. 签名:将按钮编码作为姓名的签名
  2. 排序:按签名(按钮编码)将姓名排序

查询时用二分查找找到所查询的按钮编码,将按钮编码对应的姓名全部输出。

4.二分查找与排序

排序最明显的用法就是给元素排序,这既可作为系统规范的一部分,也可作为二分查找程序的准备条件。

二分查找算法:

//循环实现
int binary_search(const vector<int> &iv,int key){
    int low = 0;
    int high = iv.size()-1;
    while(low <= high){
        int mid = low+(high-low)/2;
        if(key == iv[mid]){
            return mid;
        }
        else if(key<iv[mid]){
            high = mid-1;
        }
        else{
            low = mid+1;
        }
    }
    return -(low+1);//查询的关键字不存在,low是key应该插入的位置
}
//递归实现
int binary_search( const vector<int> &iv, int low, int high, int key)
{
   int mid = low + (high - low) / 2; // Do not use (low + high) / 2 which might encounter overflow issue
   if (low > high)
       return -(low+1);  //low是key应该插入的位置
   else
     {
       if (iv[mid] == key)
          return mid;
       else if (iv[mid] > key)
          return binary_search(iv, low, mid-1, key);
       else 
          return binary_search(iv, mid+1, high, key);
     }
}
原文地址:https://www.cnblogs.com/bukekangli/p/4314570.html