zoukankan      html  css  js  c++  java
  • 关于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;
        }
    };
  • 相关阅读:
    Gym
    UVALive
    UVALive
    UVALive
    UVALive
    Codeforces Round #367 (Div. 2) D. Vasiliy's Multiset Trie
    HDU 5816 Hearthstone 概率dp
    欧几里德与扩展欧几里德算法(转)
    差分约束系统详解(转)
    2016年第七届蓝桥杯C/C++程序设计本科B组决赛
  • 原文地址:https://www.cnblogs.com/xiangqi/p/12582700.html
Copyright © 2011-2022 走看看