编程珠玑第二章习题2.6(1-4)

1.考虑查找给定输入单词的所有变位词问题。我们只需在问题C进行更改存储方式即可
程序如下,用一个 HashMap<String, ArrayList<String>>(C++可用map<string,vector<stirng>> 来存储)来保存结果即可,键为标识,值为同位词构成的list

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

class WordInfo{
    public String word="";
    public String flag="";
}
public class tC {
    public static HashMap<String, ArrayList<String>>  result=new HashMap<String, ArrayList<String>>();
    public static void computeFlag(WordInfo wordInfo){
        String word=wordInfo.word;
        char[] flag=word.toCharArray();
        Arrays.sort(flag);
        System.out.print(wordInfo.word);
//  方案一:    for(int index=0;index<flag.length;index++){
//          wordInfo.flag+=flag[index];
//      }
        int count,index;
        for(index=0;index<flag.length;index++){
            count=1;
            while( (index+1<flag.length) && ( flag[index]==flag[index+1] )){
                count++;
                index++;
            }
            wordInfo.flag+=flag[index];
            if(count>1){
                wordInfo.flag+=count;
            }
        }
        System.out.println(" "+wordInfo.flag);
        ArrayList<String> sameSpellWord=result.get(wordInfo.flag);
        if(sameSpellWord==null){
            sameSpellWord=new ArrayList<String>();
            sameSpellWord.add(wordInfo.word);
            result.put(wordInfo.flag,sameSpellWord);
        }
        else{
            sameSpellWord.add(wordInfo.word);
//          result.put(wordInfo.flag,sameSpellWord);
        }
    }
    public static void main(String args[]){
        WordInfo wordsInfo[]=new WordInfo[10];
        String words[]={"tops","stop","pots","posited","deposit","posited","topside","cholecystoduodenostomy","duodenocholecystostomy","rubber"};
        for(int i=0;i<10;i++){
            wordsInfo[i]=new WordInfo();
            wordsInfo[i].word=words[i];
            computeFlag(wordsInfo[i]);
        }
//      for(int i=0;i<10;i++){
//          System.out.println(wordsInfo[i].word+" 的同位词有: ");
//          for(int j=0;j<10;j++){
//              if(i!=j&&wordsInfo[i].flag.equalsIgnoreCase(wordsInfo[j].flag)){
//                  System.out.print(wordsInfo[j].word+"\t");
//              }
//          }
//          System.out.println();
//      }
        System.out.println(result);
    }
}

2.给定一个包含4300 000 000个32位整数的顺序文件,如何找出一个出现至少两次的整数。
直接上代码,然后进行解释。

    #include <iostream>
    #include <math.h> 
    using namespace std;
    /* a, b, c,都是三个等长的数组,
    a数组用来保存要探测的所有的值
    b数组用来保存当前bit位为1的数
    c数组用来保存当前bit为为0的数 
    aLen表示a数组的其长度。
    bit表示开始从哪一位测试,当然首先从最高位开始,然后递减。
    比如32位。bit=32.(以测试数据中的最大数的最高位为准,如最大数为15(1111)则取4,若最大数为30(11110)则取5 
    */ 
    void printArr(int a[],int length){
        for(int i=0;i<length;i++){
            cout<<a[i]<<" ";
        } 
        cout<<endl;
    } 
    int get_same(int *a, int *b, int *c, int aLen, int bit)  
    {  
        int theSameNumber=0, flag= 0, bLen = 0, cLen, i = 0;
        int shouldHaveAmounts=pow(2,bit);  
         //flag用来与数值进行与操作,来对数值进行分类;bLen用来表示b数组长度,cLen用来表示c数组长度 

        while (bit--)  
        {  
            flag = (1 << bit);  
            for (bLen = cLen = i = 0; i < aLen&&bLen<(shouldHaveAmounts/2+1)&&cLen<(shouldHaveAmounts/2+1); ++i)
            //每进行一次循环就判断,当前是否有子数组的长度超过应有长度的一半,超过就退出  
            {  
                if (a[i] & (flag)) b[bLen++] = a[i];  //当a[i]当前bit位为1时存入b数组 
                else c[cLen++] = a[i];  //当a[i]当前bit位为0时存入c数组 
            }  
            if (bLen>cLen)  //找到分出来的更长的数组,此时表示b数组更长, 
            {  
                theSameNumber += flag;  //当为b数组时加上对应的高位为1的换算值(1<<bit) 
                a = b;
                aLen = bLen; 
                printArr(a,aLen); 
            }  
            else  
            {  
                a=c;
                aLen = cLen; 
                printArr(a,aLen);  
            }  
            shouldHaveAmounts/=2;
        }  
        return theSameNumber;  
    }  
    int main(){
        int originalArr[17]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,14,15};
        int category1[17];
        int category0[17];
        int theSameNumber=get_same(originalArr,category1,category0,17,4);
        cout<<theSameNumber;
    }

运行结果图片
此程序,可以在问题A的问题上稍作修改即可得到。
如上述程序的测试数据,假设现在的最高位为第四位,2的4次方为16,所有理应至多有16个数才不会导致数值重复,而所给数据为<=15的17个数,那么此时必定存在重复出现的数值。我们判断数值的当前最高位,若为1,则分入b数组;若为0,则分入c数组,与此同时不断检测b数组或是c数组的长度是否存在超过应有数目的一半,若超过则退出循环;然后测试下一位,将应有数目减半,重复上述的分类行为;最终bit为-1跳出循环得到值。

3.杂耍向量旋转算法: 更改了变量的名称方便理解点,也做了输入测试

#include<iostream>
#include<math.h>
#define arrayLength 10
using namespace std;
char x[arrayLength]="adeghcesh"; 
int gcd(int bigger,int smaller){
    int rest=bigger%smaller;
    while(rest>0){
        bigger=smaller;
        smaller=rest;
        rest=bigger%smaller;
    }
    return smaller;
}
void printArr(int charArrLength){
        for(int i=0;i<charArrLength;i++){
            cout<<x[i]<<" ";
         }
         cout<<endl;
}
 void playSwap(int leftMoveLength,int charArrLength){
    for(int i_moveStart=0;i_moveStart<gcd(leftMoveLength,charArrLength);i_moveStart++){
        //找到需要以哪个元素作为开始进行移动覆盖,i_moveStart表示第一个需要被覆盖元素的下标 
        char temp=x[i_moveStart];
        int i_beOverrided=i_moveStart;//i_beOverrided需要被覆盖的下标 
        while(true){
            int i_doOverride=i_beOverrided+leftMoveLength;
            if(i_doOverride>=charArrLength)
                i_doOverride-=charArrLength;
            if(i_doOverride==i_moveStart)
                break;
            x[i_beOverrided]=x[i_doOverride];
            printArr(charArrLength);
            i_beOverrided=i_doOverride;
        }
        x[i_beOverrided]=temp;
        printArr(charArrLength);
    }
    printArr(charArrLength);
}
 int main(){
    playSwap(3,arrayLength-1);
 }

运行结果图
4.略过,性能测试喜欢的可用自己试试

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值