1、两个数交换,不用temp
x = x ^ y;
y = x ^ y;
x = x ^ y;
x ^= y;
y ^= x;
x ^= y;
2、string 数字转整形数据
string temp = "-123456";
int output = atoi(temp.c_str());
//也可以用 stoi 就不用换成char*
int output = stoi(temp);
3、string 提取某一段子string
string temp = "HELLO";
temp = temp.substr(1,2);//第一个参数是从哪个下标开始,第二个参数是取几个字符
cout << temp;
4、string 的操作
string.insert(要插入的位置,插入的数量,插入什么)
string.push_back();
string.pop_back();
string.back();//指向string的末尾
string.begin();//指向string的开头
string.find();//寻找一个字符,返回其索引位置 如果没有找到的话就到会string::npos这么一个东西
to_string((int) temp);//将整数变成string
for(auto c:string)//for 循环,取的是string中的每一个字符
//也可以写成 for(char c: string)
//对于形如这样的字符串,有空格,如果需要取每一个小段的字符串可以用istringstream函数
string temp = "alice is a good girl she is a good student";
while (words >> w) tmp.push_back(w);//生成了一个列表
reverse(temp.begin(),temp,end());//翻转字符串
5、unordered_set的操作
用哈希表做快速查找,有可能需要定义一个新的hash函数,都是重载(), 关于set和unordered_set
struct pair_hash
{
template
std::size_t operator() (const std::pair& p) const
{
auto h1 = std::hash()(p.first);
auto h2 = std::hash()(p.second);
return h1^h2;
}
};
unordered_set m(nums1.begin(), nums1.end()); //初始化的方法,nums1是一个vector
m.erase(a) //既查找了m中是否存在a,又完成了删除a的工作
6、1005 K 次取反后最大化的数组和
用计数排序的方法+数组下标维护最小数的索引,很巧妙。
7、 1029 两地调度
用数学表达式化解求极值的抽象问题,太六了。
8、对于函数的返回值,如果是vector可以这样写(350. 两个数组的交集 II)
return vector (nums1.begin(),nums.begin()+k);//可以节省空间
9、记不住的vector 的基础知识
vector temp({a,b,c});//定义temp变量的时候顺便往里面放了三个元素
vector.insert():
iterator insert( iterator loc, const TYPE &val );
void insert( iterator loc, size_type num, const TYPE &val );
void insert( iterator loc, input_iterator start, input_iterator end );
insert() 函数有以下三种用法:
在指定位置loc前插入值为val的元素,返回指向这个元素的迭代器,
在指定位置loc前插入num个值为val的元素
在指定位置loc前插入区间[start, end)的所有元素 .
10、返回整数的相应二进制数字1的个数
C++ 自带的函数__builtin_popcount(x)
还可以用递归的方法
bit[i]=bit[i>>1]+(i&1);
11、136. 只出现一次的数字:给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
用异或运算
12、找到众数,169题给的是这个众数的数量大于n.size()/2,题解中的随机法很有意思,多随机几次,数量越多的数中奖概率越大。第二种是Moore投票法,(但是这种方法使用的地方受限)。如果我们把众数记为 +1+1,把其他数记为 -1−1,将它们全部加起来,显然和大于 0
,从结果本身我们可以看出众数比其他数多。
13、颠倒给定的 32 位无符号整数的二进制位。
一开始想的就是int ->string ->reverse->int,麻烦。
参考一个题解,从32位整数的本质上解决的问题
uint32_t ans=0;
//进制的本质
int i=32;
while(i--)
{
ans<<=1;
ans+=n&1;
n>>=1;
}
return ans;
这里也有一个讲位运算的文章
14、单个字符的操作
islower(char c) 是否为小写字母
isuppper(char c) 是否为大写字母
isdigit(char c) 是否为数字
isalpha(char c) 是否为字母
isalnum(char c) 是否为字母或者数字
toupper(char c) 字母小转大
tolower(char c) 字母大转小
15、对于二进制某一位进行操作
int temp = xxxxx;
temp |= 1<
16、不用比较符号比大小
本质是平均值法: max(a, b) = ((a + b) + abs(a - b)) / 2
主要是如何完成abs运算
以int8_t为例:分析运算:(var ^ (var >> 7)) - (var >> 7)
var >= 0: var >> 7 => 0x00,即:(var ^ 0x00) - 0x00,异或结果为var
var < 0: var >> 7 => 0xFF,即:(var ^ 0xFF) - 0xFF,var ^ 0xFF是在对var的全部位取反,-0xFF <=> +1, 对signed int取反加一就是取其相反数。
17、1042. 不邻接植花
涉及到图论的题,一般先构建邻接表或者是邻接矩阵。
18、设计哈希表
使用链地址法 705. 设计哈希集合
19、缩减搜索空间 167. 两数之和 II - 输入有序数组
O(n^2) ->>>>>>> O(n)
20、 448. 找到所有数组中消失的数字
给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次。
找到所有在 [1, n] 范围之间没有出现在数组中的数字。
您能在不使用额外空间且时间复杂度为O(n)的情况下完成这个任务吗? 你可以假定返回的数组不算在额外空间内。
高级解法:由于1<=a[i]<=n,所以我们可以在a[i]-1这个位置统计a[i]出现的次数,同时为了不影响其他数字的统计,只需要加数组长度就行。
一般就用 set
21、 最大公约数 gcd函数 1071. 字符串的最大公因子
通用模板
int gcd(int x, int y)
{
while (y ^= x ^= y ^= x %= y);
return x;
}
22、1018. 可被 5 整除的二进制前缀
class Solution {
public:
vector prefixesDivBy5(vector& A) {
vector res(A.size(),false);
int pre(0);
vector what_five_divided = { 0,1,2,3,4,0,1,2,3,4,0,1,2,3,4,0,1,2,3,4,0,1,2,3,4,0,1,2,3,4,0,1,2,3,4,0,1,2,3,4,0,1,2,3,4,0,1,2,3,4 };//这个地方不错,用查表的方式代替pre%5,对5取余数,查表比除法更快。
for (int i = 0; i < A.size(); i++)
{
pre = pre << 1;
pre += A[i];
if (what_five_divided[pre] == 0)
{
res[i] = true;
}
pre = what_five_divided[pre];//这个地方再取余,对于5的倍数,*2后还是5的倍数,对于余数为1的数,就可以把它当做1来看
}
return res;
}
};
23、1089. 复写零
如果正向遍历找不到最优的处理方法就试试反向遍历数组。
24、计算排列组合个数的模板,计算Cnm的
long long jiecheng(int i)
{
long long int tt = 1;
for(int j = 2;j <= i;j++)
{
tt *= j;
}
return tt;
}
long long jiecheng(int i,int j)
{
long long int tt = 1;
for(;i >= j;i--)
{
tt *= i;
}
return tt;
}
int cnm(int n,int m)
{
return jiecheng(n,n-m+1)/jiecheng(m);
}
25、 基姆拉尔森计算公式 根据年月日 计算今天是星期几。。。。我也是佛了
string dayOfTheWeek(int day, int month, int year) {
if(month==1||month==2) month+=12,year--;
int iWeek = (day+2*month+3*(month+1)/5+year+year/4-year/100+year/400)%7; //基姆拉尔森计算公式
string result[]= { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday","Sunday"};
return result[iWeek];
}
26、找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
//鸽巢原理
int findRepeatNumber(vector& nums) {
for(int i = 0;i < nums.size();++i)
{
if(nums[i] == i)
continue;
if(nums[nums[i]] == nums[i])
return nums[i];
int tmp = nums[i];
nums[i] = nums[nums[i]];
nums[tmp] = tmp;//注意这里不要写成nums[nums[i]] = tmp;
}
return 0;
}
27、290. 单词规律 (参考205题题解)
给定一种规律 pattern
和一个字符串 str
,判断 str
是否遵循
相同的规律。
这里的 遵循 指完全匹配,例如, pattern
里的每个字母和字符串 str
中的每个非空单词之间存在着双向连接的对应规律。
28、160. 相交链表
跟树一样,得到的启发就是如果优化不下去了,可以试试把一个数据结构接在他的末尾处,比如把一个链表接在另一个链表后面延长一下,或者是把一个子树的根接在另一个树结点的下面,可能会解决问题。
输入: pattern = "abba", str = "dog cat cat dog"
输出: true
输入: pattern = "aaaa", str = "dog cat cat dog"
输出: false
复制205题题解评论区的方法:大概就是将两个不同的字符串
将第一个出现的字母映射成 1,第二个出现的字母映射成 2
对于 egg
e -> 1
g -> 2
也就是将 egg 的 e 换成 1, g 换成 2, 就变成了 122
对于 add
a -> 1
d -> 2
也就是将 add 的 a 换成 1, d 换成 2, 就变成了 122
egg -> 122, add -> 122
都变成了 122,所以两个字符串异构。
28、初始化一个map
map map1={{key1,value1},{key2,value2}};
29、二分法 STL
binary_search(arr[],arr[]+size , indx)
/*arr[]: 数组首地址 size:数组元素个数 indx:需要查找的值*/
//lower_bound:查找第一个大于或等于某个元素的位置。
lower_bound(arr[],arr[]+size , indx):
/*arr[]: 数组首地址 size:数组元素个数 indx:需要查找的值*/
//upper_bound:查找第一个大于某个元素的位置。
upper_bound(arr[],arr[]+size , indx):
/*arr[]: 数组首地址 size:数组元素个数 indx:需要查找的值*/
lower_bound( begin,end,num,greater() ):从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num,greater() ):从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
30、字符串 459. 重复的子字符串
给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。
输入: "abab"
输出: True
解释: 可由子字符串 "ab" 重复两次构成。
假设给定字符串s可由一个子串x重复n次构成,即s=nx。
现构造新字符串t=2s,即两个s相加,由于s=nx,则t=2nx。
去掉t的开头与结尾两位,则这两处的子串被破坏掉,此时t中包含2n-2个子串。
由于t中包含2n-2个子串,s中包含n个子串,若t中包含s,则有2n-2>=n,可得n>=2,由此我们可知字符串s可由一个子串x重复至少2次构成,判定为true;反之,若t中不包含s,则有2n-2
这个思路的确好,但是无法套用其他题目
31、 我怎么发现,把两个输入字符串相加也是一种思路呢?
面试题 01.09. 字符串轮转
32、获取map的key的方法
map tmp;
for (auto tt : tmp)
cout << tt.first << " " << tt.second << endl;
33、七进制(类似十进制,二进制,就是不断取余)
while ( num > 0)
{
rest = num % 7 + '0';
num = num / 7;
s = rest + s;
}
34、约瑟夫环的公式+生动推导。重点是关注剩下的最后一个人的位置是0,然后反推。
https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/solution/huan-ge-jiao-du-ju-li-jie-jue-yue-se-fu-huan-by-as/
35、