C++ LeetCode 刷题经验、技巧及踩坑记录【一】

前言

记录一些小技巧以及平时不熟悉的知识。


正文


c++ 计时器

#include <chrono>   
using namespace std;
using namespace chrono;

auto start = system_clock::now();
// do something...
auto end   = system_clock::now();
auto duration = duration_cast<microseconds>(end - start);
cout <<  "花费了" 
     << double(duration.count()) * microseconds::period::num / microseconds::period::den 
     << "秒" << endl;

string 操作效率

string tmp="XXX";
tmp.clear(); 比 tmp=""; 效率高
tmp.push_back("x"); 比 tmp+= "X"; 效率高

引用传递与值传递

for(auto &c:s)与for(auto c:s)的区别

for(auto c:s)中s为一个容器,效果是利用c遍历并获得s容器中的每一个值,但是c无法影响到s容器中的元素。
for(auto &c:s)中加了引用符号,可以对容器中的内容进行赋值,即可通过对c赋值来做到容器s的内容填充。

使用for(auto &c:s)时,直接引用原字符串进行遍历操作。
使用for(auto c:s)时,逻辑上会复制一个s字符串再进行遍历操作。
由于复制一个字符串花费了大量的时间,所以第一种用法的程序执行速度要快于第二种用法。

凡是遇到时间超限,首先检查一下是不是使用了值传递。


vector 快速遍历

遍历vector时,相对于index++ ,直接擦除vector的第一个元素,每次读取0索引位置的元素速度快得多,当然,这只能用于后续不需要这个vector的情况,如 LeetCode297题解

vector.erase(vector.begin());
vector[0];
效率比
vector[index];
index++;
快得多

同一工程下避免出现同名的类

在使用unordered_map时,在类里最好是通过引用传递,如果使用private私有数据形式,在本地VS2022下运行会报错,但在LeetCode上却能正常运行。如LeetCode652题解

class Solution {
    
    
public:
    string dfs(TreeNode* root, vector<TreeNode*>& res, unordered_map<string, int>& mp){
    
    
        if(root==NULL) return "";
        //二叉树先序序列化
        string str = to_string(root->val) + "," + dfs(root->left, res, mp) + "," + dfs(root->right, res, mp);
        if(mp[str]==1){
    
    
            res.push_back(root);
        } 
        mp[str]++;
        return str;
    }

    vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
    
    
        vector<TreeNode*> res;
        unordered_map<string, int> mp;
        dfs(root, res, mp);
        return res;
    }
    };

正常运行

class Solution {
    
    
private:
    vector<TreeNode*> res;
    unordered_map<string, int> mp;

public:
    string dfs(TreeNode* root, vector<TreeNode*>& res, unordered_map<string, int>& mp){
    
    
        if(root==NULL) return "";
        //二叉树先序序列化
        string str = to_string(root->val) + "," + dfs(root->left, res, mp) + "," + dfs(root->right, res, mp);
        if(mp[str]==1){
    
    
            res.push_back(root);
        } 
        mp[str]++;
        return str;
    }

    vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
    
    
        dfs(root, res, mp);

        return res;
    }

};

报错
在这里插入图片描述

这个奇怪的问题困扰了我很久,目前可以通过该方法解决,但依旧搞不清原因。

终于知道上述报错的原因了
因为我的VS项目里有多个同名类函数(大量的Sulotion类),凡是类里面有 vector 或者 unordered_map 私有变量的,都要避免同名,否则会在类的析构时抛出异常而中断。
中断通常出现在 xmemory 或者 xhash 文件中

在这里插入图片描述


位运算>> 取均值

int mid = (l + r) >> 1;

归并排序框架

class Solution_912 {
    
    
    vector<int> tmp;
    void mergeSort(vector<int>& nums, int l, int r) {
    
    
        if (l >= r) return;
        int mid = (l + r) >> 1;
        IC(l + r);
        IC(mid);
        mergeSort(nums, l, mid);
        mergeSort(nums, mid + 1, r);
        int i = l, j = mid + 1;
        int cnt = 0;
        while (i <= mid && j <= r) {
    
    
            if (nums[i] <= nums[j]) {
    
    
                tmp[cnt++] = nums[i++];
            }
            else {
    
    
                tmp[cnt++] = nums[j++];
            }
        }
        // 即j>r,右半数组完成排序
        while (i <= mid) {
    
    
            tmp[cnt++] = nums[i++];
        }
        //即i>mid,左半数组完成排序
        while (j <= r) {
    
    
            tmp[cnt++] = nums[j++];
        }
        //将排序好的tmp复制给nums
        for (int i = 0; i < r - l + 1; ++i) {
    
    
            nums[i + l] = tmp[i];
        }
    }
public:
    vector<int> sortArray(vector<int>& nums) {
    
    
    	//给tmp开辟空间,都存0
        tmp.resize((int)nums.size(), 0);
        mergeSort(nums, 0, (int)nums.size() - 1);
        return nums;
    }
};

vector执行 resize() 默认初始化

如果使用vector的resize()之前其大小(size()==0)为0,则resize()会给每个初始化;如果之前大小不为0,则之前部分的值不变,后面扩充的空间的值会初始化。

vector<bool> color;
vector<bool> visited;
color.resize(n);
visited.resize(n);   //这里默认初始化为0(也就是false)

索引小于0的报错

提交代码运行,出现以下报错则仔细检查索引。

Line 1034: Char 34: runtime error: addition of unsigned offset to 0x602000000150 overflowed to 0x601efafafc48 (stl_vector.h)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:1043:34

并查集框架

/*Union - Find 算法的复杂度可以这样分析:
构造函数初始化数据结构需要 O(N) 的时间和空间复杂度;
连通两个节点 union、判断两个节点的连通性 connected
、计算连通分量 count 所需的时间复杂度均为 O(1)。*/
class UF
{
    
    
private:
	vector<int>parent;
	int count;
public:
	UF(int n)
	{
    
    
		/// @brief 初始化
		/// @param n 
		count = n;
		for (int i = 0; i < n; i++)
		{
    
    
			parent.push_back(i);
		}
	}

	int find(int x)
	{
    
    
		/// @brief 找根节点
		/// @param x 
		/// @return 
		if (x != parent[x])
		{
    
    
			parent[x] = find(parent[x]);
		}
		return parent[x];
	}

	void unite(int x, int y)
	{
    
    
		/// @brief 连接两个节点
		/// @param x 
		/// @param y 
		parent[find(x)] = find(y);
		count--;
	}

	bool isConnected(int x, int y)
	{
    
    
		/// @brief 判断两节点是否连接
		/// @param x 
		/// @param y 
		/// @return 
		return parent[find(x)] == find(y);
	}
};


猜你喜欢

转载自blog.csdn.net/m0_50910915/article/details/128999832