单词长度的最大乘积

题目:
输入一个字符串数组words,请计算不包含相同字符的两个字符串words[i]和words[j]的长度乘积的最大值。如果所有字符串都包含至少一个相同字符,那么返回0。假设字符串中只包含英文小写字母。例如,输入的字符串数组words为[“abcw”,“foo”,“bar”,“fxyz”,“abcdef”,],数组中的字符串"bar"与"foo"没有相同的字符,他们长度的乘积为9。"abcw"与"fxyz"也没有相同的字符,它们长度的乘积为16,这是该数组不包含相同字符的一对字符串的长度乘积的最大值。

用类似哈希表方法记录字符串中出现的字符

因为这个题目假设所有字符都是英文小写字母,因此最多只需要在每个字符串对应的哈希表中查询26次就能判断两个字符串是否包含有相同字符。因此可以用一个长度为26的布尔型数组来模拟哈希表。数组下标为0的值表示字符’a’是否出现,下标为1的值表示字符’b’是否出现,其余以此类推。
**

代码分两步:
第一步:
建立二维布尔型数组,将每个字符串字符的存在情况一一判别存入数组中(初始化每个字符串对应的哈希表)
第二步:
根据记录完成的表判别两个字符串之间对应表的位置上的字符的存在的布尔值之间的关系,然后根据关系分别对应执行相关操作(根据哈希表判断没对字符串是否包含相同的字符)
**

代码如下:

 /*用哈希表记录字符串中出现的字符*/
    public int MaxProduct(String[] args)
    {
        boolean[][] flags = new boolean[args.length][26];
        //用一个二维数组存储字符串数组的每一个字符串以及其对应的字符串中a~z中对应字符是否出现
        for (int i = 0;i<args.length;i++)//遍历字符串数组,提取其中每个字符串
        {
            for(char str:args[i].toCharArray())//将字符串转化为字符数组,然后逐一辨别,并对应序号下标存储a~z中哪个字符是否出现
            {
                flags[i][str-'a'] = true;
            }

        }
        int result = 0;
        for (int i = 0;i<args.length;i++)
        {
            for(int j = i+1;j<args.length;j++)
            {
                int k = 0;
                for(;k<26;k++)
                {
                    /*如果字符串i和字符串j对应为k上判断值都为true,则跳出循环,例如两个字符串k=1位上都为true,则说明两个字符串内都包含有b字符*/
                    if (flags[i][k]&&flags[j][k])
                    {
                        break;
                    }
                }
                /*若k==26,则说明为执行break语句即两个字符串之间没有相同字符,则计算长度乘积并比较大小,并返回赋值。*/
                if (k==26)
                    result = Math.max(result, (args[i].length()*args[j].length()));


            }
        }
        return result;
    }

用整数的二进制数位记录字符串中出现的字符

在二进制中数字的每个数位要么是0要么是1。因此,可以将长度为26的布尔型数组用26个二进制的数位代替,二进制的0对应布尔值的false,而1对应true。
可以用一个int型整数记录某个字符串中出现的字符。如果字符串中包含’a’,那么整数最右边的数位为1;如果字符串中包含’b’,那么整数的倒数第2位为1,其余以此类推

如果两个字符串中包含相同的字符,那么它们对应的整数相同的某个数位都为1,两个整数的与运算将不会等于0.如果两个字符串没有相同的字符,那么它们对应的整数的与运算的结果等于0.

例下图解:
在这里插入图片描述
代码如下:

 /*用整数的二进制数位记录字符串中出现的字符*/
    public int MaxProduct2(String[] args)
    {
        int[] flags = new int[args.length];
        for(int i=0;i<args.length;i++)
        {
            for(char num:args[i].toCharArray())
            {
                flags[i] |= 1<<(num-'a');//利用或 和 左移运算,计算将是否出现字符转化为二进制对应位上为0还是1,进而判断。
            }
        }
        int result = 0;
        for (int i=0;i<args.length;i++)
        {
            for(int j=i+1;j<args.length;j++)
            {
                if((flags[i]&flags[j])==0)
                {
                    result = Math.max(result,(args[i].length()*args[j].length()));
                }
            }
        }
        return result;
    }

上述代码中的整数"flag[i]"用来记录字符串"words[i]"中出现的字符。如果"words[i]"中出现了某个字符ch,则对应的整数"flag[i]"中从右边数起第ch-'a’个数位(即’a’对应最右边的数位,'b’对应倒数第2个数位,其余以此类推)将被标记为1。

如果两个整数flags[i]和flags[j]的与运算的结果为0,那么它们对应的字符串"works[i]"和"works[j]"一定没有相同的字符

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

回家种蜜柚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值