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<class T1, class T2>
std::size_t operator() (const std::pair<T1, T2>& p) const
{
auto h1 = std::hash<T1>()(p.first);
auto h2 = std::hash<T2>()(p.second);
return h1^h2;
}
};
unordered_set<int> m(nums1.begin(), nums1.end()); //初始化的方法,nums1是一個vector
m.erase(a) //既查找了m中是否存在a,又完成了刪除a的工作
6、1005 K 次取反後最大化的數組和
用計數排序的方法+數組下標維護最小數的索引,很巧妙。
7、 1029 兩地調度
用數學表達式化解求極值的抽象問題,太六了。
8、對於函數的返回值,如果是vector可以這樣寫(350. 兩個數組的交集 II)
return vector<int> (nums1.begin(),nums.begin()+k);//可以節省空間
9、記不住的vector 的基礎知識
vector<T> 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<<k;//對temp對應的二進制第k位進行操作。
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)
給定一個範圍在 1 ≤ a[i] ≤ n ( n = 數組大小 ) 的 整型數組,數組中的元素一些出現了兩次,另一些只出現一次。
找到所有在 [1, n] 範圍之間沒有出現在數組中的數字。
您能在不使用額外空間且時間複雜度爲O(n)的情況下完成這個任務嗎? 你可以假定返回的數組不算在額外空間內。
高級解法:由於1<=a[i]<=n,所以我們可以在a[i]-1這個位置統計a[i]出現的次數,同時爲了不影響其他數字的統計,只需要加數組長度就行。
一般就用 set<int> 利用唯一性檢查。
21、 最大公約數 gcd函數 1071. 字符串的最大公因子
通用模板
int gcd(int x, int y)
{
while (y ^= x ^= y ^= x %= y);
return x;
}
class Solution {
public:
vector<bool> prefixesDivBy5(vector<int>& A) {
vector<bool> res(A.size(),false);
int pre(0);
vector<int> 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<int>& 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<char,int> 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<type>() ):從數組的begin位置到end-1位置二分查找第一個小於或等於num的數字,找到返回該數字的地址,不存在則返回end。通過返回的地址減去起始地址begin,得到找到數字在數組中的下標。
upper_bound( begin,end,num,greater<type>() ):從數組的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<n,可得n<2,n只能爲1,由此我們可知字符串s=x,假定的子串就爲s本身,判定爲false。
這個思路的確好,但是無法套用其他題目
31、 我怎麼發現,把兩個輸入字符串相加也是一種思路呢?
32、獲取map的key的方法
map<int ,int> 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,然後反推。
35、