力扣每日一题748.最短补全词之非专业选手做法 遍历+排序

题目描述:

给你一个字符串 licensePlate 和一个字符串数组 words ,请你找出并返回 words 中的 最短补全词 。

补全词 是一个包含 licensePlate 中所有的字母的单词。在所有补全词中,最短的那个就是 最短补全词 。

在匹配 licensePlate 中的字母时:

1.忽略 licensePlate 中的 数字和空格 。

2.不区分大小写。

3.如果某个字母在 licensePlate 中出现不止一次,那么该字母在补全词中的出现次数应当一致或者更多。

例如:licensePlate = "aBc 12c",那么它的补全词应当包含字母 'a'、'b' (忽略大写)和两个 'c' 。可能的 补全词 有 "abccdef"、"caaacab" 以及 "cbca" 。

请你找出并返回 words 中的 最短补全词 。题目数据保证一定存在一个最短补全词。当有多个单词都符合最短补全词的匹配条件时取 words 中 最靠前的 那个。

 题目分析:

1.需要处理字符串licensePlate,提取出字母,题目要求不区分大小写,所以可以在提取字母的时候把字母全转换成小写字母,可以用tolower函数;

2.在words里面找到所有满足条件的单词,所满足的条件是:单词里面需要有字符串licensePlate所提取出来的所有字母;

3.把满足条件的单词放到一个对象数组p里面,对象的类per内有三个成员变量,分别用来放单词,单词的长度,单词的位置;

4.对数组进行排序,按照长度排序和位置排序,注意:长度排序的优先级大于位置排序;

5.这种遍历字符串的做法,需要注意的一点是:若效字母个数大于1的时候,已经遍历过的字母需要被覆盖掉,使之后面继续遍历是不会被重复计数;比如测试样例1中

 字符串licensePlate中被提取出来的有效字母分别是"s p s t",(为了方便理解把第一个s和第二个s区分开,设有效字母是"s1 p s2 t"),但在遍历过程中,s1在碰到step的s时就计数,然后break;s2再碰到step的s时也会计数,那么step的s就会被重复计数;

所以解决方式是当s被计数后,就用"."替换掉;但是我们需要把有效单词放到p里面,单词的字母被改动了那输出就会出现问题,因此,我们可以先把words复制到另一个数组wordss里面,当words里面的单词满足条件,根据位置相同,把相同位置上的wordss里面的单词放到p里面就可以了;

代码:

class per
{
public:
    string t;//满足条件的单词
    int a;//单词的位置
    int mlen;//单词的长度
    bool operator<(const per& w ) const{
        if(mlen==w.mlen)
        {
            return a<w.a;
        }
        return mlen<w.mlen;
}
};
class Solution {
public:
    string shortestCompletingWord(string licensePlate, vector<string>& words) {
        vector<string> wordss;
        vector<char> l;
        for(int i=0;i<licensePlate.length();i++)
        {
            if(isalpha(licensePlate[i]))
            {
                l.push_back(tolower(licensePlate[i]));
            }
        }
        int y=0;
        int l_len=l.size();//有效字母的长度
        int words_len=words.size();//单词的个数
        for(int i=0;i<words_len;i++)
        {
            wordss.push_back(words[i]);

        }
        per p[words_len];
        for(int i=0;i<words_len;i++)
        {
            int str_len=0;//每个单词的长度
            str_len=words[i].size();
            int count=0;//用来计数字母
            
            if(str_len>=l_len)
            {
                for(int k=0;k<l_len;k++) {
                    for (int j = 0; j < str_len; j++) {
                        if (l[k] == tolower(words[i][j])) {
                            words[i][j]='.';
                            count++;
                            break;
                        }
                    }

                    if(count==l_len)
                    {
                        p[y].t=wordss[i];
                        p[y].a=i;
                        p[y].mlen=wordss[i].length();
                        y++;
                    }

                }

            }

        }

        //把p按照单词长度和位置进行排序;
        sort(p,p+y);
        return p[0].t;


    }
};

 

结果:

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值