第二章: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();
    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 -1;//查询的关键字不存在
}
//递归实现
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 - 1;
   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);
     }
}
时间: 2024-08-16 15:27:37

第二章:Rotate、变位词的相关文章

图像处理分析与机器视觉【第二章】

第二章是数字图像及其性质,开篇介绍了一些基本概念和数学工具. 首先提出了一个问题,那就是透视投影,在将3D的物体经过透视投影和转化为2D图像时,损失了大量的信息,所以通过一幅图像重构3D场景就成为了一个病态的问题. 在数学知识部分,涉及到了很多接触过但未深入了解的和从未接触过的知识点.首先是理想冲激,狄拉克分布,可以进行图像的采样.从网上找了一个相关的笔记 http://www2.math.uu.se/~maciej/courses/PDE_for_Finance/SP2013.pdf 随后是对

第二章--汇编语言 (修订版)

稍微有点儿计算机知识的朋友一定知道,计算机是只识别0和1的,最初那会儿,要写程序,就要用0和1来写,呵 呵,Cool吧!所以曾经有过的对程序员的崇拜,可能就源自那个时候吧 后来,人们发现用0和1来写程序,太不爽了,不但写起来不上手,而且回过头来看的话,应该很难再看明白了,总之出于这些原因,就有了汇编语言. 汇 编语言用一些助记符来代替0和1的多种组合,也就是各个指令,这样的话,从一定程度上来说,方便了许多(一头老牛:方便太多了)(一只菜鸟:一点儿也不方 便,完全看不懂).但是,汇编也同样不方便,

变位词的查找(上)

本文也同步发表在我的公众号"我的天空" 这次我们聊一个比较有意思的话题:变位词的查找,这个话题在<编程珠玑>中出现,此书很经典,偏向于算法,大家如果能通读的话,肯定受益匪浅!   什么是变位词 不同的单词,如果其组成的字母相同的话,那么这些单词就互为变位词,譬如pots.stop. tops这三个单词就是互为变位词,都是由字母p.o.t.s组成,但是"pot" 就不与上述单词互为变位词,其缺少字母s,"potss"也不是,其多了一个字

CareerCup之1.4判断字符串是否为变位词

[题目] 原文: 1.4 Write a method to decide if two strings are anagrams or not. 译文: 写一个函数判断两个字符串是否是变位词. [分析] 变位词(anagrams)指的是组成两个单词的字符相同,但位置不同的单词.比如说, abbcd和abcdb就是一对变位词.该题目有两种思路: [思路一] 由于变位词只是字母的顺序改变,字符长度,字符种类没有改变,所以根据此我们只要重新根据字典序排序一下,两个字符串也就一样了. The eyes

第二章 有什么理由使用Async异步编程

p { display: block; margin: 3px 0 0 0; } --> 写在前面 在学异步,有位园友推荐了<async in C#5.0>,没找到中文版,恰巧也想提高下英文,用我拙劣的英文翻译一些重要的部分,纯属娱乐,简单分享,保持学习,谨记谦虚. 如果你觉得这件事儿没意义翻译的又差,尽情的踩吧.如果你觉得值得鼓励,感谢留下你的赞,在今后每一次应该猛烈突破的时候,不选择知难而退.在每一次应该独立思考的时候,不选择随波逐流,应该全力以赴的时候,不选择尽力而为,愿爱技术的园

变位词

题目描述: 如果两个字符串的字符一样,但是顺序不一样,被认为是兄弟字符串,比如bad和adb即为兄弟字符串,现提供一个字符串,如何在字典中迅速找到它的兄弟字符串,请描述数据结构和查询过程. 思路一:用计数排序 设计一个数组,对单词每个字母计数加1,对兄弟单词每个字母计数减去1,如果最后这个数组的计数是0,那么就为兄弟单词 bool isBrotherWord(string &str1, string &str2) { int len1 = str1.length(); int len2 =

统计学习方法 笔记&lt;第二章 感知机&gt;

第二章 感知机 感觉感知机这东西还是很简单的,随便写点. 感知机(perceptron)是二分类的线性分类器. 输入x表示实例的特征向量,输出y为实例的类别,由如下函数表示: 其中w为权值(weight)或权值向量(weight vector),b表示偏置(bias),sign为符号函数,里面的东西大于0就是1,否则是-1. 感知机属于判别模型(直接寻找输入到输出的映射函数,不关心联合概率什么的). 感知机的解释:wx + b = 0 对应于特征空间中的一个超平面S(超平面这个东西在二维上表示为

第二章 知识图谱——机器大脑中的知识库

第二章 知识图谱——机器大脑中的知识库 作者:刘知远(清华大学):整理:林颖(RPI) 版权所有,转载请注明出处 知识就是力量.——[英]弗兰西斯·培根 1 什么是知识图谱 在互联网时代,搜索引擎是人们在线获取信息和知识的重要工具.当用户输入一个查询词,搜索引擎会返回它认为与这个关键词最相关的网页.从诞生之日起,搜索引擎就是这样的模式,直到2012年5月,搜索引擎巨头谷歌在它的搜索页面中首次引入“知识图谱”:用户除了得到搜索网页链接外,还将看到与查询词有关的更加智能化的答案.如下图所示,当用户输

变位词的查找(下)

本文也同步发表在我的公众号"我的天空" 实现方案优劣的思考 之前我们的实现方案的优点是一旦目标词库的签名建立后,则变位词的查找会变得简单而快速:缺点是由于在生成目标词库时,要为每个词都生成签名,导致生成词库的时间会变慢,同时会消耗空间.对于那些没有被查找到的字符串的签名实际上是浪费的. 测试结果:在CPU为Inter Core i3-2328M,内存为6GB的PC上生成数量为1万的目标词库平均时间为377毫秒,查找变位词的平均时间为11毫秒.   第二种方案 在生成目标词库的时候并不生