交替合并字符串
两串字符串,word1 与word2 将字符串中的字符依此交替合并到新字符串中,从word1开始,此时关于字符串的长度有三种可能性,1 > 2, 1 = 2, 1 < 2。所以我们需要知道字符串的长度才能对这三种可能进行判别,因为是合并到一个字符串里面所以需要创建一个新的字符串,又知道关于string类可以进行尾插,也就是重载了 += 我们需要对字符串进行遍历以便能够进行交叉合并,在for循环中,我们将中间的判断条件更换为 i < m || i > n 这样就能满足可以进行遍历完成,所以我们进行尾插两个下标相同的字符串中的字符,并且设置一个判定条件,当 i >= n或者m的时候代表这个字符串遍历结束,由于world1先插入,所以world放在前面,之后判断第二个。
class Solution { public: string mergeAlternately(string word1, string word2) { int n = word1.size(), m = word2.size(); string annex; for(int i = 0; i < m || i < n ; i++) { if(i < n) { annex += word1[i]; } if(i < m) { annex += word2[i]; } } return annex; } };
找不同
这个没什么可说的,最简单的方法就是利用 ASCII进行求和,之后将两个数相减,得出的ASCII值就是多出来的字母,还有暴力求解那太麻烦了,就不写了
class Solution { public: char findTheDifference(string s, string t) { int i = 0 , j = 0; for(char e : s) { i += e; } for(char e : t) { j += e; } return j - i; } };
还有一种非常高效的方法就是用异或进行求解。位运算符( & | ^ )是作用于整数类型的运算对象。它是二进制位进行计算,也就是内存中的值(补码)进行计算,异或的计算规则是二进制位相同为0,相异为1。在某些情况下,char类型也可以作为异或操作符的操作数 如 char a = 'A' , b = 'B' ; ASCII码值为65与66,而 char c = a^b; 实际上是对65和66进行异或操作。以上都是废话,如果有基础就不用看了
重点:这里解题用到了异或的几个特征
a ^ b = b ^ a。
(a ^ b)^ c = a ^ (b ^ c)。
a ^ a = 0。a ^ 0 = a。
a ^ a ^ a = a
2 ^ 3 = 3 ^ 2。
(2 ^ 3)^ 4 = 2 ^ (3 ^ 4)。2
^ 2 = 0。2^ 0 = 2。2
^ 2^ 2 = 2
而我们以"abcd"和"abcda"进行异或就是
a ^ b ^ c ^ a ^ b ^ c ^ a = (a^a^a)^(b^b)^(c^c) 又因为自身异或的结构为0
(a^a^a)^(b^b)^(c^c) = (a)^0^0 = a^0 = a 这样就得出了被添加的字符
所以解题的重点思路:利用遍历将两个字符串中的全部字符,进行异或得到多出的字符。
class Solution { public: char findTheDifference(string s, string t) { int i = 0 ; for(char e : s) { i ^= e; } for(char e : t) { i ^= e; } return i; } };
找出字符中第一个匹配项的下标
这种题是字符串匹配的题,求解方法有两种。一种是BF算法(暴力求解),一种是KMP算法,由三个大佬发明的算法,KMP算法较为复杂会单独写一篇博客,进行复习使用
BF的实现思路:现有两个字符串,str1与str2,将str1的字符依此与str2的字符相比较,若遇见两个不相同的字符,从str1字符的现有位置跳到下一个字符上在重新进行比较,直到比较结束。代码实现就是遍历两个字符串,进行上述规则的比较。双重for循环进行遍历,如果str1的剩余字符的个数与str2的个数相同,还没有比较成功就说明不存在相同的字符串了,因为这时候str1的字符个数比str2的个数还要小就没有比较的必要了。所以遍历str1的结束条件就是下标 <=(str1的符个数-str2的字符个数)。str2正常遍历,之后就是在str2中的判断,如果第一轮遍历没有相同的,那么str1的下标就要被str2的下标多了1,第二轮多了2,所以在进行判断的时候我们str的下标就是 ( i + j ), 这样每次循环str1的下标就会向前移动一位,if判断条件是两个字符不相等使用continue跳出内部循环,str1下标加一在重新判断,如果成功则输出 i 那就是它的初始下标。
class Solution { public: int strStr(string haystack, string needle) { int n = haystack.size(), m = needle.size(); for( int i = 0; i <= (n - m); i++) { bool flag = true; for(int j = 0; j < m; j++) { if(haystack[i+j] != needle[j]) { flag = false; continue; } } if(flag) { return i; } } return -1; } };
有效的字母异位词
读题我们得到,有两个字符串均为小写,若这两个字符串出现的字符个数和次数相同那么输出true,简单来说就是,两个字符排序后字符相同那么就是字母异位词,那么就很简单了,对两个字符串进行排序如果字符串相等则输出true,否则输入false。然后首先可以对两个字符串的个数进行计算,如果不相等那么不用排序直接输入false即可。其中sort函数可以对一组数据进行升序排序,其函数原型是 void sort (RandomAccessIterator first, RandomAccessIterator last); 这道题也可以用哈希表进行解题
class Solution { public: bool isAnagram(string s, string t) { if(s.size() != t.size()) { return false; } sort(s.begin(), s.end()); sort(t.begin(), t.end()); if(s == t) { return true; } return false; } };
移动零
经典双指针的题,定义两个指针,同时在首元素,right为快指针,left为慢指针。当right位置的元素为0向下走,当元素不为零将right位置的元素赋值给left。双方一起向下走。等走完之后,left到right的位置就是0的位置,然后将这些位置赋值为零即可
class Solution { public: void moveZeroes(vector<int>& nums) { int right = 0, left = 0; while(right < nums.size() ) { if(nums[right] == 0) { right++; } else { nums[left] = nums[right]; right++; left++; } } for(left; left< nums.size(); left++) { nums[left] = 0; } } };
加一
这个题的意思就是给你一个数字里面存放有数字,1,2,3将他想象成123+1 = 124变成了1,2,4.类似于这个有三种情况,上面是一种情况,还有一种情况是 1,2,9想象成129+1就变成了1,3,0.还有一种情况就是9,9,9就变成了999+1为 1,0,0,0.根据这三种情况来写代码。那么代码实现就很简单了。for循环从最后一个位置开始,如果是第一种情况,不为9对最后一个位置加1直接返回,如果最后一位为9,那么最后一位变成0,向后走一位吗,在判断是否为9不为9加+直接返回,为9举行向后走一位判断,当下标为0的时候进行最后的判断,如何还是为9那么就令他等于零,在使用insert函数,在指定位置插入一位元素,1。begin()就代表首元素。
class Solution
{
public:
vector<int> plusOne(vector<int>& digits)
{
for(int i = digits.size() - 1; i >= 0; i--)
{
if(digits[i] != 9)
{
digits[i] += 1;
return digits;
}
else
{
digits[i] = 0;
if( i == 0)
{
digits.insert(digits.begin(), 1);
}
}
}
return digits;
}
};
数组元素积的符号
这个题没什么好说的非常简单
class Solution { public: int arraySign(vector<int>& nums) { int sign = 1; for(int num : nums) { if(num == 0) { return 0; } if(num < 0) { sign = -sign; } } return sign; } };
判断能否形成等差数列
首先进行判断,如果数组只有一位则构不成等差数量,然后将前一个元素和后一个元素相减得出公差,进行循环,如果是等差数列则前一位减去后一位不为公差则返回false如果循环完毕说明是等差数量返回true
class Solution { public: bool canMakeArithmeticProgression(vector<int>& arr) { sort (arr.begin(), arr.end()); int j = arr[1] - arr[0]; if(arr.size() < 2) { return false; } for(int i = 1; i < arr.size(); i++) { if((arr[i] - arr[i-1]) != j) { return false; } } return true; } };
单调数列
这个题利用了逻辑与,全假为假,一个for循环解决问题,设置两个bool类型,进行循环,进行判断单调递增为假,递减为加,如果一个为假,说明出现了单调增或者减,逻辑与仍为真,如果全部为假说明这个数组同时有前一个数比后一个数大或小,那么不是单调,全假为假。
class Solution { public: bool isMonotonic(vector<int>& nums) { bool m = true, n = true; for(int i = 1; i <nums.size(); i++ ) { if(nums[i] - nums[i - 1] > 0) { m = false; } if(nums[i] - nums[i - 1] < 0) { n = false; } } return m || n ; } };
最后一个单词的长度
这题是从最后进行遍历,但是需要考虑到,如果最后一个是几个空格该怎么办,所有加入了bool类型如果遍历到字符了bool类型变成正确,如果没有遍历到字符那就是错误,并且只有bool是正确且当前元素为空格才能说明题最后一个字母遍历完成了
class Solution { public: int lengthOfLastWord(string s) { char n = ' '; int m = 0; bool flag = false; for(int i = s.size()-1; i >= 0; i--) { if(s[i] == ' ' && flag) { return m; } if(s[i] != n) { flag = true; m++; } } return m; } };
机器人能否返回原点
这个题很简单,机器人上下左右移动,要想返回原地上下左右的次数必须一样才行,所以定义两个变量,上下一个变量为0向上++ 向下-- ,左右同理。当两个变量为零。则说明返回了原点。
class Solution { public: bool judgeCircle(string moves) { int x = 0, y = 0; for(const char& e : moves) { if( e == 'R') { x++; } else if (e == 'L') { x--; } else if (e == 'U') { y++; } else if (e == 'D') { y--; } } return x == 0 && y == 0; } };
在区间范围内统计奇数数目
while循环,当low > high的时候说明区间的树取完了。如果 low % 2== 1是奇函数,直接加2就可以得到下一个奇函数,设置n代表奇函数的个数,如果是偶函数加一就是奇函数了。
class Solution {
public:
int countOdds(int low, int high)
{
int n = 0;
while(low <= high)
{
if(low % 2 == 1)
{
low += 2;
n++;
}
else if(low % 2 == 0)
{
low ++;
}
}
return n;
}
};