LC刷题记录2

第二篇

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

具体思维如图
leetcode 上题解链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值