Loading

关于Leetcode解题提升(一)

题目总结:

一.拼写单词

二.最长回文串

三.水壶问题

四.两数之和

五.最小的K个数

题目来源:https://leetcode-cn.com/problems/find-words-that-can-be-formed-by-characters

 

扎实基础,最为重要。

 

 

题目一:拼写单词

给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars。

假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我们就认为你掌握了这个单词。

注意:每次拼写(指拼写词汇表中的一个单词)时,chars 中的每个字母都只能用一次。

返回词汇表 words 中你掌握的所有单词的 长度之和。

 

示例 1:

输入:words = ["cat","bt","hat","tree"], chars = "atach"
输出:6
解释:
可以形成字符串 "cat" 和 "hat",所以答案是 3 + 3 = 6。
示例 2:

输入:words = ["hello","world","leetcode"], chars = "welldonehoneyr"
输出:10
解释:
可以形成字符串 "hello" 和 "world",所以答案是 5 + 5 = 10。
 

提示:

1.1 <= words.length <= 1000
2.1 <= words[i].length, chars.length <= 100
3.所有字符串中都仅包含小写英文字母



解题思路:观察题目,有words字符串数组和chars字符数组,需要判断的是chars中的内容能否组成words中的字符串,并且将能够组成的字符串的长度输出,由此可知,只需要创建两个哈希表,一个保存chars中字母出现的次数,一个保存当前访问到的words中的字符串,然后去一一对比键值,若chars中对应字母出现的次数大于words当前访问到的字符串,则能够组成,用变量保存长度之和即可。

 

class Solution {
public:
    int countCharacters(vector<string>& words, string chars) {
        unordered_map<char,int> char_cnt;
        for(char c : chars)
        ++char_cnt[c];
        int ans = 0;
        for(string word : words)
        {
            unordered_map<char,int> word_cnt;
            for(char c : word)
            ++word_cnt[c];
            bool flag = true;
            for(char c: word)
                if(char_cnt[c] < word_cnt[c])
                {
                    flag = false;
                    break;
                }
            

            if(flag)
            ans+=word.size();
        }
        return ans;
    }
};

 

 

题目二:最长回文串

给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。

在构造过程中,请注意区分大小写。比如 "Aa" 不能当做一个回文字符串。

注意:
假设字符串的长度不会超过 1010。

示例 1:

输入:
"abccccdd"

输出:
7

解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。

 

题目解析:一开始的思维是构建哈希表,存储字母出现的次数,然后根据回文串的特性,偶数次的字母可以全部使用,奇数次的字母使用偶数次(只有一个奇数串可以全部使用),也就是说,我们只需要判断有多少个奇数次的字母,减去出现的次数,最后长度加上1,就是我们所需要得到的答案。

 

class Solution {
public:
    int longestPalindrome(string s) {
          unordered_map<char,int> chars_cnt;
          for(char c : s)
              ++chars_cnt[c];
          
          int Odd_num = 0;
          for(auto i : chars_cnt)
          {
           int v = i.second;
           Odd_num+=v%2;     
          }
          return Odd_num == 0 ? s.length() : s.length() - Odd_num + 1; 
    }
};

 

题目三:水壶问题

这个题目真是纠结了我很久很久,一开始是想列出所有状态,用BFS去搜索能够得到的状态来作对比,然后runtime直接暴毙,后来才知道个贝祖定力(也称裴蜀定理),可以非常非常方便的解决水壶问题,也就是利用最大公约数去求解,

但是为了验证该题目可以用裴蜀定理去解决,花了大量时间(还是太年轻了),验证过程如下(字丑别在意):

 

技巧性的方法就是这样,熟能生巧,理解问题要从不同角度去看。

class Solution {
public:
    int gcd(int x,int y)
    {
        if(x%y==0)return y;
        return gcd(y,x%y);
    }
    bool canMeasureWater(int x, int y, int z) {
      if(x+y<z)return false;
      else if(x==z||y==z)return true;
      else if(x==0||y==0) return z==x||x+y==z;
      else return z%gcd(x,y) == 0;
    }
};

 

题目四:两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

 

题目解析:又是一道建表题,该题两种解法,第一肯定是毫无美观可言的暴力搜,遍历整个数组,排列所有组合,输出答案,时间复杂度最坏情况为O(N^2),对于严格的runtime要求,估计会立马凉凉,所以需要一点技巧性,创建一个哈希表,

存下nums中所有元素的下标,然后遍历nums数组,在哈希表中寻找是否存在target - nums[?],且设置条件不重复访问即可。利用到了find函数。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {

        unordered_map<int,int> Hashmap;

        for(int i=0;i<nums.size();i++)
            Hashmap[nums[i]] = i;         
        
        for(int i=0;i<nums.size();i++)
        {
            if(Hashmap.find(target-nums[i]) != Hashmap.end() && Hashmap[target-nums[i]] != i)    
                return {i , Hashmap[target-nums[i]]};
        }
        return {};
    }
};

 

题目五:最小的k个数

输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

 

示例 1:

输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]
示例 2:

输入:arr = [0,1,2,1], k = 1
输出:[0]
 

题目解析:该题比较简单,偷懒直接用了优先队列的迭代器输出。

class Solution {
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
        priority_queue<int, vector<int>, greater<int> > sf_arr;
        for(int i : arr)
        sf_arr.push(i);
        vector<int> finished_arr;
        for(int i = 0 ; i < k ; i++)
        {
            finished_arr.push_back(sf_arr.top());
            sf_arr.pop();
        }
        
        return finished_arr;
    }
};

 

posted @ 2020-03-27 17:24  eveilcoo  阅读(243)  评论(0编辑  收藏  举报