zoukankan      html  css  js  c++  java
  • 字符串类的算法题

    1、将0-1串进行排序,你可以交换任意两个位置,问最少交换多少次?(用快速排序的思想)

    int answer=0;
    for(int i=0,j=len-1;i<j;++i,--j){
        while((i<j)&&(a[i]=='0'))
        ++i;
       // for(;(i<j)&&(a[i]=='0');++i));
        while((i<j)&&(a[j]=='1'))
        --j;
       //for(;(i<j)&&(a[j]=='1');--j);
        if(i<j)
        ++answer;
    }

    2、删除所有的a,并复制所有的b(字符数组足够大)

      1>先删除a,可以利用原来的字符串空间

    int n=0,numb=0;
    for(int i=0;a[i];++i){
      if(s[i]!='a'){
         s[n++]=a[i];       
      }  
      if(s[i]=='b'){
          ++numb;
       }
    }

      2>复制b,技巧:倒着复制

    int newLength=n+numb;
    
    s[newLength]=0;
    
    for(int i=newLength-1,j=n-1;j>=0;--j){
    
      s[i--]=s[j];
    
      if(s[j]=='b'){
    
        s[i--]='b';
      }
    
    }

    3、一个字符串只包含*和数字,请把字符串内所有的*都放在开头

    方法一:数字的相对顺序会变

    for(int i=0,j=0;j<n;++j){
    
      if(s[j]=='*')
    
        swap(s[i++],s[j])
    }

    方法二:数字的相对顺序不变

    int j=n-1;
    
    for(int i=n-1;i>=0;--i){
    
      if(isdigit(s[i]))
    
        s[j--]=s[i];
    }
    
    for(;j>=0;--j){
    
      s[j]='*';
    
    }

    4、给定两个串a,b,问b是否是a的子串的变位词,例如输入a=hello,b=lel,lle,ello都是true,但是b=elo是false,

      解题思想:

      滑动窗口的思想,动态维护一个窗口,例如b的长度为3,我们考察a[0..2],a[1..3],a[2..4]是否和b是变位词。

      用一个hash,基于字符串的特性,用一个[0..255]或[0..65535]的数组,在这,暂且认为它们都是小写英文字母,用[0-25]来表示b中的每个单词出现的次数

          用nonZero来存出现不同字母的个数,num[]来存每个字母出现的个数

      1>先遍历一下b,存b中的不同字母的个数nonZero,和每个字母出现的个数num[];

    int nonZero=0;
    for(int i=0;i<lenb;++i){
    
      if(++num[b[i]-'a']==1)
    
      ++nonZero;
    
    }

      2>再遍历a[0..lenb-1],用b中的次数减去a中的一个窗口内字符种类,如果结果全是0,则找到这样的子串,注意:num[]的含义变为字符种类差。

      for(int i=0;i<lenb;++i){
    
        int c=a[i]-'a';
        --num[c];
        if(num[c]==0){
    //b与a中的该字母个数差为0,正好,可以将nonZero减1了
          --nonZero;
        }else if(num[c]==-1){
    //这种情况不是b中没有这个字母,就是a中该字母个数比b中要多
          ++nonZero;
        }
      }
      if(nonZero==0)
    
        return true;

      3>a窗口滑动右移

      i=lenb;
    
      新窗口:a[i-lenb+1..i]
    
      旧窗口:a[i-lenb..i-1]
    
      需要去掉a[i-lenb],加入a[i]
      for(int i=lenb;i<lena;++i){
        //去掉旧窗口的第一个字母,将它(b与nonZero)返回到原来的状态
        int c=a[i-lenb]-'a';
        ++num[c];
        if(num[c]==1){
          ++nonZero;
        }else if(num[c]==0){
    
          --nonZero;
        }
        //加入新窗口的最后一个字母,因为中间的字母与旧窗口重叠。
        c=a[i]-'a';
        --num[c];
        if(num[c]==0){
          --nonZero;
        }else if(num[c]==-1){
    
          ++nonZero;
        }
        if(nonZero==0)
          return true;
    }    

    5、单词翻转

      while(i<j){swap(s[i++],s[j--]);}

    例1: I'm a student变为student a I'm

    方法:先将整个句子翻转,tneduts a m'I

      再将每个单词单独翻转,student a I'm

    例2:字符串循环移位 abcd

      bcda,cdab,dabc

     思路: 长度为n,移动m次,相当于移动m%n次

      将前m%n翻转,再将后n-m%n翻转,最后总体翻转一下

     

      

      

  • 相关阅读:
    fetch用法说明
    正则表达式贪婪与非贪婪模式
    export ,export default 和 import 区别 以及用法
    理解MVC 框架
    HTTP 请求方法介绍
    Http协议--请求报文和响应报文
    一、Web 如何工作的
    前端工程师进阶之路-总纲
    前端知识体系之CSS及其预处理器SASS/LESS
    进度条
  • 原文地址:https://www.cnblogs.com/yuxingyoucan/p/6558599.html
Copyright © 2011-2022 走看看