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;
}
};