第二篇
关于map
内部实现机理不同
map: map内部实现了一个红黑树(红黑树是非严格平衡二叉搜索树,而AVL是严格平衡二叉搜索树),红黑树具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素。因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行的操作。map中的元素是按照二叉搜索树(又名二叉查找树、二叉排序树,特点就是左子树上所有节点的键值都小于根节点的键值,右子树所有节点的键值都大于根节点的键值)存储的,使用中序遍历可将键值按照从小到大遍历出来。
unordered_map: unordered_map内部实现了一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序是无序的。
原文链接:https://blog.csdn.net/BillCYJ/article/details/78985895
3. 无重复字符的最长子串
类kmp算法,可以用unordered_map建立<char,int> 对应关系
进一步优化,用 vector table(128,-1)
char c = s[i];
int pos = (int) c;
用数组优化map
代码如下:
class Solution {
public: int lengthOfLongestSubstring(string s) {
int l=s.length();
vector <int> table(128,-1);
int start=0,end=0,ans=0;
while(end<l){
char now = s[end];
if(table[(int)now]>=start){
start = table[(int)now]+1;
}
table[(int)now] = end;
end++;
int temp = end-start;
ans = max(ans,temp);
}
return ans;
}
};
8. 字符串转换整数
atoi( ) 函数会扫描参数 nptr字符串,跳过前面的空白字符(例如空格,tab缩进等,可以通过isspace( )函数来检测),直到遇上数字或正负符号才开始做转换,而再遇到非数字或字符串结束时(’\0’)才结束转换,并将结果返回。如果 nptr不能转换成
int 或者 nptr为空字符串,那么将返回 0。
C++中若需要将string类型转为int类型,需先将string转为const char*。
具体使用如下:
char *s = "12345";
string str("56789");
int ints = atoi(s); //这种写法可以
int ints = atoi(str);//**写法错误,必须将string转为char***
int ints = atoi(str.c_str()); //写法可以
🌟剑指offer 数组重复数字
时间O(n),空间O(1)
法一:鸽巢,每次循环一定产生nums[i]==i,依次类推,直到找到第一个nums[i] = m,其中nums[m]==m.
即第i位上的数m与之前第m位上的数m相等,说明已经出现过一次m。判断成功。
代码如下:
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int l = nums.size();
for(int i=0;i<l;i++){
int m = nums[i];
while(i!=nums[i]){
if(nums[m] == m) return m;
swap(nums[i],nums[m]);
}
}
return -1;
}
};
法二:
借鉴别人方法,将数组nums视为hashtable,根据第i位上的数m的正负符号判断之前是否出现过数字i。如果出现过,则i即为重复数字;否则将nums[i]改为 -nums[i],继续向下判断。
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int l = nums.size();
for(int i=0;i<l;i++){
int now = abs(nums[i]);
if(nums[now]<0) return now;
nums[now] = -1*nums[now];
}
return 0;//只有+0 =-0情况 才可能执行到这一步
}
};
190 颠倒二进制位
一个整数a, a & 1 这个表达式可以用来判断a的奇偶性。二进制的末位为0表示偶数,最末位为1表示奇数。使用a%2来判断奇偶性和a & 1是一样的作用,但是a & 1要快好多。
(传说百分之60以上)
class Solution {
public:
uint32_t reverseBits(uint32_t n) {
string str;
uint32_t ans = 0;
int i = 32;
while(i--){
ans<<=1; // ans *= 2;
int temp = n&1; //int temp = n%2;
ans += temp;
n>>=1; // n/=2;
}
return ans;
}
};
unordered_map 计数方法
1.count函数
size_type count ( const key_type& key ) const
count函数用以统计key值在unordered_map中出现的次数。实际上,c++ unordered_map不允许有重复的key。因此,如果key存在,则count返回1,如果不存在,则count返回0.
2.find函数
iterator find ( const key_type& key );
如果key存在,则find返回key对应的迭代器,如果key不存在,则find返回unordered_map::end。因此可以通过
102.二叉树的层序遍历
记录结点所在层次,不用在每个节点数据结构中单独增加一个数据段,也不用增加hashtable。理想做法是在遍历时,先统计queue.size(),然后for循环遍历queue.size()即可。
代码如下:
while(!q.empty()){
int l = q.size();
vector <int> thislevel;
for(int i=0;i<l;i++){
TreeNode* front = q.front();
q.pop();
thislevel.push_back(front->val);
if(front->left!=NULL) q.push(front->left);
if(front->right!=NULL) q.push(front->right);
}
v.push_back(thislevel);
}
202.快乐数
法1.开map,当出现重复数字时,代表着进入循环,此时若不为1,则一定无法重复迭代到1,判断为false;
class Solution {
public:
int getsum(int x){
int tot = 0;
while(x){
int now = x%10;
tot += now*now;
x /= 10;
}
return tot;
}
bool isHappy(int n) {
unordered_map <int,int> mp;
while(n!=1){
if(mp[n]==0){
mp[n] = 1;
n = getsum(n);
}else{
return false;
}
}
return true;
}
};
法2.空间上优化,不用开map,使用快慢指针。
类似于检测环形链表,如果给定的数字最后一直重复循环,那么快指针一定会追上慢指针,也就是两者一定会相等,此时判断为false;如果没有循环重复,那么最后两者也会相等,且等于1.
如下:
class Solution {
public boolean isHappy(int n) {
int fast=n;
int slow=n;
do{
slow=squareSum(slow);
fast=squareSum(fast);
fast=squareSum(fast);
}while(slow!=fast);
//循环结束标志一定为slow == fast
if(fast==1)
return true;
else return false;
}
private int squareSum(int m){
int squaresum=0;
while(m!=0){
squaresum+=(m%10)*(m%10);
m/=10;
}
return squaresum;
}
}
240.搜索二维矩阵II
类似滑动窗口,从左下角开始:
1)若相等,返回真
2)若小于目标值,则舍弃所在列,即i++
3)若大于目标值,则舍弃所在行,即j–
代码如下:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int m = matrix.size();
if(m==0) return false;
int n = matrix[0].size();
if(n==0) return false;
if(target < matrix[0][0] || target>matrix[m-1][n-1]){
return false;
}
int i = m-1 , j = 0;
while(i>=0 && j<n){
if(matrix[i][j] == target){
return true;
}else if(matrix[i][j] > target){
i--;
}else{
j++;
}
}
return false;
}
287.寻找重复数字
类似快慢指针,查找是否存在环,
int findDuplicate(vector<int>& nums) {
int len = nums.size();
int slow = 0 , fast = 0;
while(1){
slow = nums[slow];
fast = nums[nums[fast]];
if(slow == fast){
break;
}
}
int now = 0;
while(now!=slow){
slow = nums[slow];
now = nums[now];
}
return now;
}