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

前言

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


vector 计数

计数

//记录与首元素相同的数字的个数,因为数组有序,并且最多出现4次,所以不用遍历所有区间
    int cnt = count(nums.begin(), nums.begin() + 4, nums[0]);

vector 逆序

reverse(ans.begin(),ans.end()){ans.rbegin(),ans.rend()}

vector 删除首位元素

vector<int> nums_new(nums.begin() + 1,
                             nums.end());//去掉一个首元素(顺子的第一个)
nums_new.erase(find(nums_new.begin(), nums_new.end(),
                            nums[0] + 1));//去掉一个首元素+1(顺子的第二个)                          

vector二维数组排序

#include <iostream>
#include <vector>
#include <algorithm>

bool customSort(const std::vector<int>& a, const std::vector<int>& b) {
    if (a[0] < b[0]) {
        return true;  // 第一列升序排列
    } else if (a[0] > b[0]) {
        return false;
    } else {
        return a[1] > b[1];  // 第二列降序排列
    }
}

void sortTwoDimensionalArray(std::vector<std::vector<int>>& arr) {
    std::sort(arr.begin(), arr.end(), customSort);
}

如果是在类中使用,要将custom设为static 静态函数。原因如下

为什么cmp函数在作为类成员函数的时候一定需要static修饰呢?这是因为所有我们在类内定义的非static成员函数在经过编译后隐式的为他们添加了一个this指针参数!变为了:

bool cmp(Solution *this, int a, int b)

而标准库的sort()函数的第三个cmp函数指针参数中并没有这样this指针参数,因此会出现输入的cmp参数和sort()要求的参数不匹配,从而导致了:
error: reference to non-static member function must be called
而我们知道static静态类成员函数是不需要this指针的,因此改为静态成员函数即可通过!

或者( LeetCode354官方题解 ):

        sort(envelopes.begin(), envelopes.end(), [](const auto& e1, const auto& e2) {
            return e1[0] < e2[0] || (e1[0] == e2[0] && e1[1] > e2[1]);
        });

这个更简洁更易理解。


vector二维数组初始化

常用与动态规划中DP Table的建立。

以下代码将创建一个 i 行 j 列的二维矩阵,并全部初始化为-1。

dp = vector<vector<int>>(i, vector<int>(j, -1));

以下代码将创建一个 m+1 行 n 列的二维矩阵,默认初始化为 0。

vector<vector<int>> dp(m+1,vector<int>(n+1));

C++ 不同进制输出

C++中以四种进制进行输出

#include <iostream>
#include <bitset>
 
using namespace std;
 
int main()
{
    int a=64;
    cout<<(bitset<32>)a<<endl;//二进制32位输出
    cout<<oct<<a<<endl;//八进制
    cout<<dec<<a<<endl;//十进制
    cout<<hex<<a<<endl;//十六进制
    return 0;
}


C++ 位运算

参考
&
按位与
如果两个相应的二进制位都为1,则该位的结果值为1,否则为0
|
按位或
两个相应的二进制位中只要有一个为1,该位的结果值为1
^
按位异或
若参加运算的两个二进制位值相同则为0,否则为1
~
取反
~是一元运算符,用来对一个二进制数按位取反,即将0变1,将1

举例:

   1000101             1000101         1000101         1000101
 & 0101100          |  0101110      ~               ^  0101110
 = 0000100           = 1101111       = 0111010         1101011

<<左移运算符:expr1<<expr2 表示 expr1 左移 expr2 位,数值上表示 expr1 扩大了 2^expr2 倍;
>> 右移运算符:expr1>>expr2表示 expr2 右移 expr2 位,数值上表示 expr1 缩小了 2^expr2 倍;

左移就是扩大 2 移位数 2^{移位数} 2移位数 ,右移就是缩小 2 移位数 2^{移位数} 2移位数

  1. 左移运算符
    左移运算符为:<<
    将一个运算对象的各二进制位全部左移若干位;
    左边的二进制位丢弃,右边补0;
    若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2。
  2. 右移运算符
    右移运算符为:>>
    将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃;
    操作数每右移一位,相当于该数除以2;
    左补0还是补1,得看被移数是正还是负。
  3. 总结
    number << n; // number乘以2的n次幂
    number >> n; // 如果number为非负,则用number除以2的n次幂
    这些移位运算符类似于十进制中移动小数点来乘以或除以10

应用:将十进制转为二进制并统计二进制中1的位数。

在这里插入图片描述


C++ lower_bound()

参考

C++ STL标准库中除了基于顺序查找的 find()、find_if()、search() 等,还提供有 lower_bound()、upper_bound()、equal_range() 以及 binary_search() 这 4 个查找函数,它们的底层实现采用的都是二分查找的方式。

lower_bound() 函数用于在指定区域内查找不小于目标值的第一个元素。也就是说,使用该函数在指定范围内查找某个目标值时,最终查找到的不一定是和目标值相等的元素,还可能是比目标值大的元素。

lower_bound() 函数定义在头文件中,其语法格式有 2 种,分别为:

//在 [first, last) 区域内查找不小于 val 的元素
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last,
                             const T& val);
//在 [first, last) 区域内查找第一个不符合 comp 规则的元素
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last,
                             const T& val, Compare comp);

其中,first 和 last 都为正向迭代器,[first, last) 用于指定函数的作用范围;val 用于指定目标元素;comp 用于自定义比较规则,此参数可以接收一个包含 2 个形参(第二个形参值始终为 val)且返回值为 bool 类型的函数,可以是普通函数,也可以是函数对象。
实际上,第一种语法格式也设定有比较规则,只不过此规则无法改变,即使用 < 小于号比较 [first, last) 区域内某些元素和 val 的大小,直至找到一个不小于 val 的元素。这也意味着,如果使用第一种语法格式,则 [first,last) 范围的元素类型必须支持 < 运算符。

此外,该函数还会返回一个正向迭代器,当查找成功时,迭代器指向找到的元素;反之,如果查找失败,迭代器的指向和 last 迭代器相同。

再次强调,该函数仅适用于已排好序的序列。所谓“已排好序”,指的是 [first, last) 区域内所有令 element<val(或者 comp(element,val),其中 element 为指定范围内的元素)成立的元素都位于不成立元素的前面。

例子

#include <iostream>     // std::cout
#include <algorithm>    // std::lower_bound
#include <vector>       // std::vector
using namespace std;
//以普通函数的方式定义查找规则
bool mycomp(int i,int j) { return i>j; }

//以函数对象的形式定义查找规则
class mycomp2 {
public:
    bool operator()(const int& i, const int& j) {
        return i>j;
    }
};

int main() {
    int a[5] = { 1,2,3,4,5 };
    //从 a 数组中找到第一个不小于 3 的元素
    int *p = lower_bound(a, a + 5, 3);
    cout << "*p = " << *p << endl;

    vector<int> myvector{ 4,5,3,1,2 };
    //根据 mycomp2 规则,从 myvector 容器中找到第一个违背 mycomp2 规则的元素
    vector<int>::iterator iter = lower_bound(myvector.begin(), myvector.end(),3,mycomp2());
    cout << "*iter = " << *iter;
    return 0;
}

程序执行结果为:

*p = 3
*iter = 3

注意,myvector 容器中存储的元素看似是乱序的,但对于元素 3 来说,大于 3 的所有元素都位于其左侧,小于 3 的所有元素都位于其右侧,且查找规则选用的是 mycomp2(),其查找的就是第一个不大于 3 的元素,因此 lower_bound() 函数是可以成功运行的。


C++ pair

pair将一对值(T1和T2)组合成一个值,

    这一对值可以具有不同的数据类型(T1和T2),

    两个值可以分别用pair的两个公有函数first和second访问。

C++ stack 和 queue

头文件

#include<queue>// 队列 
#include<stack>//栈

定义

stack<int>  s;
queue<int>  q; 

常用操作

栈:
s.empty()//如果栈为空返回true,否则返回false  
s.size()//返回栈中元素的个数  
s.pop()//删除栈顶元素但不返回其值  
s.top()//返回栈顶的元素,但不删除该元素  
s.push(X)//在栈顶压入新元素 ,参数X为要压入的元素
队列:
q.empty()// 如果队列为空返回true,否则返回false  
q.size() // 返回队列中元素的个数  
q.pop()  //删除队列首元素但不返回其值  
q.front()  // 返回队首元素的值,但不删除该元素  
q.push(X) //在队尾压入新元素 ,X为要压入的元素
q.back() //返回队列尾元素的值,但不删除该元素 

两栈实现队和两队实现栈是常见的简单题,画个图就好了,要点是两个栈(或栈)做好分工,有主次的去使用。


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WoooChi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值