内容参考CyC大佬的LeetCode复习指南
在考虑更优解时,先从数据状况入手,一般C++1s可以运行 1 0 7 − 1 0 8 10^7 - 10^8 107−108次,看有何特点可以利用,如有序,回文,重复,推公式等
适用于有序查找。求重复元素最左或最右时推出判断为 l < h。
int lower_bound(int A[], int l, int r, int x) {
while (l < r) {
int m = l + (r - l) / 2;
if (A[m] >= x)
r = m;
else
l = m + 1;
}
return l;
}
int upper_bound(int A[], int l, int r, int x) {
while (l < r) {
int m = l + (r - l) / 2;
if (A[m] > x)
r = m;
else
l = m + 1;
}
return l;
}
模板:
while (l < r) {
int m = l + (r - l) / 2;
if (true)
r = m;
else
l = m + 1;
}
return l;
也可用于左闭右开情况
class Solution {
public:
int uniquePaths(int m, int n) {
int m1 = m + n - 2;
int n1 = m - 1;
long long re = 1;
for (int i = 1; i <= n1; i++)
re = re * (m1 - n1 + i) / i;
return (int)re;
}
};
int findLongestChain(vector<vector<int>>& pairs) {
int ssize = pairs.size();
if (ssize < 1)
return 0;
sort(pairs.begin(), pairs.end(), [] (const vector<int> &a, const vector<int> &b) {
return a[1] < b[1];
});
int re = 1;
int end = pairs[0][1];
for (int i = 1; i < ssize; i++) {
if (end < pairs[i][0]) {
re++;
end = pairs[i][1];
}
}
return re;
}
参考背包九讲
bool isPrime(int n) {
if (n <= 1) return false;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0)
return false;
}
return true;
}
int gcd (int a,int b) {
return b == 0 ? a : gcb(b , a % b);
}
位操作实现:
int gcd(int a, int b) {
if (a < b)
return gcd(b, a)l
if (b == 0)
return a;
if ((a & 1) == 0 && (b & 1) == 0)) {
retrun 2 * gcd(a >> 1, b >> 1);
} else if ((a & 1) == 1 && (b & 1) == 0) {
return gcd(a >> 1, b);
} else if((a & 1) == 0 && (b & 1) == 1) {
return gcd(a, b >> 1);
} else {
return gcd(b, a - b);
}
]
交换两个整数
a = a ^ b;
b = a ^ b;
a = a ^ b;
110从下往上的方法
617 437 111 404 687
337使用dfs时需要对比哪个方式最大并不是路线已固定
非递归中序遍历,先用cur存当前节点,一直遍历left到底,push,弹出最左,打印,然后push该节点right,循环。
栈实现队列:队列要求先进先出,在第一个栈反转后,再用第二栈反转即可
class MyQueue {
public:
stack<int> s1,s2;
MyQueue() {
}
void push(int x) {
s1.push(x);
}
int pop() {
if (s2.empty()){
while (!s1.empty()) {
int temp = s1.top();
s1.pop();
s2.push(temp);
}
}
int re = s2.top();
s2.pop();
return re;
}
int peek() {
if (s2.empty()){
while (!s1.empty()) {
int temp = s1.top();
s1.pop();
s2.push(temp);
}
}
int re = s2.top();
return re;
}
bool empty() {
if (s1.empty() && s2.empty())
return true;
return false;
}
};
用队实现栈:栈要求后进先出,所以使用两个队列,当有push时,把q1所有元素放到q2,
再push元素,最后在q2元素放入q1即可实现栈序
class MyStack {
public:
/** Initialize your data structure here. */
queue<int> q1,q2;
MyStack() {
}
void push(int x) {
if(q1.empty()) {
q1.push(x);
} else {
while (!q1.empty()) {
int temp = q1.front();
q1.pop();
q2.push(temp);
}
q1.push(x);
while (!q2.empty()) {
int temp = q2.front();
q2.pop();
q1.push(temp);
}
}
}
int pop() {
int temp = q1.front();
q1.pop();
return temp;
}
int top() {
return q1.front();
}
bool empty() {
return q1.empty();
}
};
数组实现队:用head和tail来记录相应位置
int q[100], head = 0, tail = 0;
void push(int x) {
q[++tail] = x;
}
int pop() {
return q[++head];
}
bool empty() {
return head >= tail;
}
数组实现栈:
int s[100], head = 0;
void push(int x) {
s[++head] = x;
}
int top() {
return s[head - 1];
}
void pop() {
head--;
}
bool empty() {
return head == 0;
}
//单调队列:
// 假设解决滑动窗口问题
int a[200000];
struct node
{
int x,p;
node(){}
node(int xx,int pp){x=xx;p=pp;}
}list[200000];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1;i <= n; i++) scanf("%d", &a[i]);
int head = 1, tail = 1;
list[1] = node(a[1], 1);
for(int i = 2;i <= n; i++)
{
while(head <= tail && list[tail].x <= a[i]) tail--;//删尾,目前数比对队尾大
list[++tail] = node(a[i], i);//得到最优解并插入
while(i - list[head].p >= m) head++;//去头
if(i >= m) printf("%d\n", list[head]);
}
return 0;
特点:空间O(N),查找O(1).
class Solution {
public:
int longestConsecutive(vector<int>& num) {
if(num.size()==0)return 0;
unordered_set<int> record(num.begin(),num.end());
int res = 1;
for(int n : num){
if(record.find(n)==record.end()) continue;
record.erase(n);
int prev = n-1,next = n+1;
while(record.find(prev)!=record.end()) record.erase(prev--);
while(record.find(next)!=record.end()) record.erase(next++);
res = max(res,next-prev-1);
}
return res;
}
};
while (nums[nums[i] - 1] != nums[i])
swap(nums[i], nums[nums[i] - 1]);