每日一题 --- 力扣318----最大单词长度乘积

简介: 每日一题 --- 力扣318----最大单词长度乘积

7.png


这道题时间复杂度我感觉设置的不是很好,应该最好是有一个1000变成10000就行。


因为我在做这道题的时候被误导了,以为双重循环暴力判断一下也能过,因为1000*1000


*26的时间复杂度没有到1亿,那么我刚开始认为是能过的,结果卡在最后一个用例上了,


那么后期,我就开始想怎么优化掉那个26,26刚好可以用bitmap(状态压缩)和位运算的思想,


这样我们可以优化掉那个26的复杂度,这样我们就能过了


附上第一次暴力解法(卡在最后一个用例)

class Solution {
public:
    int vv[1100][32];
    int maxProduct(vector<string>& words) 
    {
      int n = words.size();
      for(int i = 0;i < n;i++)
      {
         for(int j = 0;j <words[i].size();j++)
         {
            if(words[i][j] < 'a' || words[i][j] > 'z') continue;
            int index = words[i][j]- 'a';
            vv[i][index]++;
         }
      }
      int ans = -0x3f3f3f3f;
      for(int i = 0;i < n;i++)
      {
          for(int j = 0;j < n;j++)
          {
              if(i == j) continue;
              else
              {
                 bool flag = false;
                 if(words[i].size() >= words[j].size())
                 {
                     for(int c = 0;c < words[i].size();c++)
                     {
                          int index = words[i][c]- 'a';
                         if(vv[i][index] && vv[j][index])
                         {
                             flag = true;
                             break;
                         }
                     }
                 }
                 else
                 {
                      for(int c = 0;c < words[j].size();c++)
                     {
                         int index = words[i][c]- 'a';
                         if(words[i][c] < 'a' || words[i][c] > 'z') continue;
                         if(vv[i][index] && vv[j][index])
                         {
                             flag = true;
                             break;
                         }
                     }
                 }
                 if(!flag) 
                 {
                     int a = words[i].size();
                     int b = words[j].size();
                     ans = max(ans,a * b);
                 }
              }
          }
      }
      return ans == -0x3f3f3f3f ? 0 : ans;
    }
};

正确解法:


利用int类型有32位,刚好可以通过32位来映射对应的26位小写字母来达到


比如


0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0


来了一个字符串"aaccb"


那么就可以映射成


1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0


有些不喜欢思考的人还会问,为什么aa这些都映射在一个地方呢


因为我们根据题目要求的是找到两个字符串中,没有相同的字符


所以一个字符串有重复的字符就可以默认只有一个这样的字符,


因为假设"aab" ,"ac" 和 "ab" , "ac",一个字符串中少一个重复字符和多一个重复


字符没什么区别,所以我们可以将一个字符串中的相同的字符直接映射到同一个位上


1代表该字符串有该字符,0代表没有


映射完之后我们怎么办呢?


//既然用到用整数进行状态压缩了,那么我们就可以根据经验也就是位运算来判断了


1 1 1 0 0 0 0 0  --- "aaabbc"


1 0 1 0 0 0 0 0  --- "aaaccc"


两个数字&一下可以得出一个数字,


  得到 (这个数字代表的色,两个字符串中,相同的字符置为1,不相同的字符置为0)


0 0 0 0 0 0 0 0


那么我们得出一个结论:


如果数字大于0,说明两个字符串中有相同的字符


如果数字等于0,说明两个字符串中没有相同的字符


本题还有一个很小很小的优化


就是双重循环的时候,我们可以去重


假设


1 2 3 4


每个数只与前面的数进行判断,那么就可以去除掉重复的组合了

class Solution {
public:
    int mask[1100];
    int maxProduct(vector<string>& words) 
    {
      int n = words.size();
      for(int i = 0;i < n;i++)
      {
         for(int j = 0;j <words[i].size();j++)
         {
            mask[i] |= (1 << (words[i][j] - 'a'));//状态压缩
         }
      }
      int ans = -0x3f3f3f3f;
      for(int i = 0;i < n;i++)
      {
        for(int j = 0;j < i;j++)
        {
           if(!(mask[i] & mask[j]))
           {
              int a = words[i].size();
              int b = words[j].size();
              ans = max(ans,a * b);
           }
        }
      }
      return ans == -0x3f3f3f3f ? 0 : ans;
    }
};
相关文章
|
1月前
Leetcode(最后一个单词长度)
这篇文章介绍了两种解决LeetCode第58题的方法,即计算给定字符串中最后一个单词的长度,方法包括翻转字符串和逆向遍历统计。
19 0
|
1月前
【LeetCode 20】151.反转字符串里的单词
【LeetCode 20】151.反转字符串里的单词
19 0
|
3月前
|
算法
LeetCode第58题最后一个单词的长度
LeetCode第58题"最后一个单词的长度"的解题方法,通过从字符串末尾向前遍历并计数非空格字符,直接得出最后一个单词的长度。
LeetCode第58题最后一个单词的长度
|
3月前
|
算法 JavaScript Python
【Leetcode刷题Python】79. 单词搜索和剑指 Offer 12. 矩阵中的路径
Leetcode第79题"单词搜索"的Python解决方案,使用回溯算法在给定的二维字符网格中搜索单词,判断单词是否存在于网格中。
42 4
|
3月前
|
Python
【Leetcode刷题Python】生词本单词整理
文章提供了一个Python程序,用于帮助用户整理和排版生词本上的单词,包括去除重复单词、按字典序排序,并按照特定的格式要求进行打印排版。
41 3
|
3月前
|
算法 Java 索引
LeetCode初级算法题:寻找数组的中心索引+x的平方根+三个数的最大乘积+Leetcode 149:直线上最多的点数 Java详解
LeetCode初级算法题:寻找数组的中心索引+x的平方根+三个数的最大乘积+Leetcode 149:直线上最多的点数 Java详解
36 0
|
3月前
|
Python
【Leetcode刷题Python】318. 最大单词长度乘积
本文提供了LeetCode题目318的Python编程解决方案,题目要求在一个字符串数组中找出两个不含有公共字母的单词,且这两个单词的长度乘积最大,如果不存在这样的两个单词,则返回0。
20 0
|
5月前
|
算法 测试技术 索引
力扣经典150题第三十二题:串联所有单词的子串
力扣经典150题第三十二题:串联所有单词的子串
26 0
|
5月前
|
算法
力扣经典150题第二十一题:反转字符串中的单词
力扣经典150题第二十一题:反转字符串中的单词
60 0
|
5月前
|
算法
力扣经典150题第十九题:最后一个单词的长度
力扣经典150题第十九题:最后一个单词的长度
31 0