LeetCode刷题【一】

292.Nim游戏

思考:当石头数为:1,2,3时,你先手,拿1~3块石头。肯定能直接获胜。如果当石头数为4时,你有三种拿的可能1,2,3.此时剩余的为3,2,1.这时候你的朋友相当于是“场面上剩下1~3块石头,并且他先手”,那么这种情况你就肯定输了。同理,当5块石头时,你拿起1~3块,剩下的为4,3,2。刚刚已经讨论了场面剩下4块的时候,无论你怎么选都是输,那么对于你的朋友也是一样。当8块石头时,你只能挑1~3块。剩下7~5块。这时该你的对手挑,所以肯定能挑出只剩4块的情况。规律就是:当桌子上的石头书为4的倍数时候,你肯定就输,否则你就能赢。

class Solution {
public:
    bool canWinNim(int n) {
        if(n%4){
            return true ;
        }
        else{
            return false;
        }
    }
};

344.翻转字符串

一开始出了个错误:Char 39: error: no matching function for call to 'Solution::reverseString(std::vector<char>&)',我还以为提交了的函数咋错了呢,后来发现题目改了“ string reverseString(string s)改成了void reverseString(vector<char>& s)”,跟符合题目的要求了吧!

解析:这样就不能直接调用STL 中的reverse函数,一个reverse(s.begin(),s.end())来直接解决问题了!

思考:首先是不要另外的数组分配额外的空间这种就说我们不能重新弄一个stack<char>类型来存储了。并且要原地修改输入数组,使用O(1)的额外空间解决问题。

class Solution {
public:
    void reverseString(vector<char>& s) {
       for(int i = 0,j = s.size()-1;i <= j ;i++,j--){
           char temp = s[i];
           s[i] = s[j];
           s[j] = temp;
       }
    }
};

557、反转字符串的单词III

思考:一开始我想的用flag来控制,当遇到' '的时候就flag =1 ,然后可以reverse,reverse之后再把flag = 0.

class Solution {
public:
    string reverseWords(string s) {
        int flag = 0;
        auto word_begin = s.begin();
       for(auto iter = s.begin();iter!=s.end();iter++){
           if(*iter == ' '){
               flag = 1;
           }
           if(flag == 1){
               reverse(word_begin,iter);
               word_begin = iter + 1 ;
               flag = 0;
           }
       } 
         reverse(word_begin,s.end());
        return s;
    }
};

后来看了别人写的代码,我才想到。。直接判断当前的字符是不是' '不就行了?是的话就reverse,不是就继续循环。reverse(iter1,iter2),iter2表示要逆转的字符的下一位。正好循环到' '。并且把word_begin 更新到 当前迭代器iter2的下一位,表示下一个单词的开头。

class Solution {
public:
    string reverseWords(string s) {
        auto begin = s.begin();
        for(auto iter = s.begin();iter!=s.end();++iter){
            if(*iter==' '){
                reverse(begin,iter);
                begin = iter+1;
            }
        }
        reverse(begin,s.end());
        
        return s;
    }
};

136.只出现一次的数字

思考:通过哈希表来构造,每个数字出现的次数。

构造哈希表:map<类型1,类型2>。

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        map<int,int> hash_map;
        for(int i = 0 ; i < nums.size();i++){
            if(hash_map.find(nums[i]) == hash_map.end()){
                hash_map[nums[i]] = 0;
            }
            hash_map[nums[i]]++;
        }
        for(int i = 0 ; i < nums.size();i++){
            if(hash_map[nums[i]]==1){
                return nums[i];
            }
        }
        return 0;
    }
};

或者提取hash_map当中的映射。

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        map<int,int> hash_map;
        for(auto item : nums){
            if(hash_map.find(item) == hash_map.end()){
                hash_map[item] = 0;
            }
            hash_map[item]++;
        }
        for(auto item : hash_map){
            if(hash_map[item.first]==1){
                return item.first;
            }
        }
        return 0;
    }
};

本体应该使用:“异或”操作,异或:0和1,两者相等为0,不等为1。【最快的操作】

因为题目中,两次,一次。说明整个数组数字都是出现2次,只有一个出现1次。

初始化result为0,和每一位进行异或操作,如[2,2,1]。这个数组,0异或2 = 2;2异或2 = 0;1异或0 = 1.求得最后需要的只出现一次的就是result。因为一个数字和自身异或为0。

class Solution {
public:
    int singleNumber(vector<int>& nums) {
     int result = 0;
        for(int i = 0 ; i < nums.size();i++){
            result ^= nums[i];
        }
        return result;
    }
};

169、求众数

思考:使用哈希表建立映射,出现次数多于n / 2 的就是我们想要找到的结果。

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int vec_size = nums.size();
        map<int,int> hash_map;
        for(int i = 0 ; i < vec_size;i++){
            if(hash_map.find(nums[i])==hash_map.end()){
                hash_map[nums[i]] = 0 ;
            }
              hash_map[nums[i]] ++ ;
        }
        for(int i = 0 ; i < vec_size;i++){
            if(hash_map[nums[i]] > vec_size / 2 ){
                return nums[i];
            }
        }
        return 0;    
    }
};

第二种解法:摩尔投票法。在任何数组中,出现次数大于该数组长度一半的值只能有一个

摩尔投票法的基本思想很简单,在每一轮投票过程中,从数组中找出一对不同的元素,将其从数组中删除。这样不断的删除直到无法再进行投票,如果数组为空,则没有任何元素出现的次数超过该数组长度的一半。如果只存在一种元素,那么这个元素则可能为目标元素。

class Solution {
public:
    int majorityElement(vector<int>& nums) {
       int n = nums[0];
       int times = 1;
        for(int i = 1 ; i < nums.size();i++){
            if(nums[i] != n){
                times--;
                if(times <= 0){
                    n = nums[i+1]; //当前这位数把出现次数消耗完了,所以应该选取的新的候选数字
                                    //肯定是当前数位的下一位。
                }
            }
            else{
                times++;
            }
        }
        return n;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_34269988/article/details/86636807