191. 位1的个数(3月22日)
分析
lowbit
code
class Solution {
public:
int hammingWeight(uint32_t n) {
int res = 0;
while (n) res ++, n -= n & (-n);
return res;
}
};
85. 不用加减乘除做加法(3月22日)
分析
将加法拆开: 不进位 + 进位
不进位的话 = 异或和
进位的话 就是算 (num1 & nums) << 1, 因为进位要向前进1位
因此这样的话, 就不涉及到加减乘除了
那么这样的过程不会不死循环呢, 如果我们每次把num1, num2换成sum和carry
会不会一定结束呢, 答案是一定会结束的
因为这两个和(num1 num2/ sum carry)一定相等
每次迭代完(计算sum和carry)
将num1 = sum, num2 = carry
当num2 == 0的时候结束, 因为当num2 = 0的时候 num1 + num2的总和 = num1
可以这样看, 比如初始的时候, 末尾有k个0, 那么(num1 & num2) 末尾至少有k个0, << 1后, (num1 & num2) << 1后至少有k + 1个0
所以每操作一次, 结尾0的个数至少会+1, 因此的话, 至少操作32次
code
class Solution {
public:
int add(int num1, int num2){
while (num2) {
int sum = num1 ^ num2;
int carry = (num1 & num2) << 1;
num1 = sum, num2 = carry;
}
return num1;
}
}
341. 扁平化嵌套列表迭代器(3月23日)
分析
先遍历一遍nestedList
取出每个List, 如果List
中元素只有一个直接push;
否则, 继续递归遍历List
code
/**
* // This is the interface that allows for creating nested lists.
* // You should not implement it, or speculate about its implementation
* class NestedInteger {
* public:
* // Return true if this NestedInteger holds a single integer, rather than a nested list.
* bool isInteger() const;
*
* // Return the single integer that this NestedInteger holds, if it holds a single integer
* // The result is undefined if this NestedInteger holds a nested list
* int getInteger() const;
*
* // Return the nested list that this NestedInteger holds, if it holds a nested list
* // The result is undefined if this NestedInteger holds a single integer
* const vector<NestedInteger> &getList() const;
* };
*/
class NestedIterator {
public:
vector<int> q;
int k = 0;
NestedIterator(vector<NestedInteger> &nestedList) {
for (auto& l : nestedList) dfs(l);
}
void dfs(NestedInteger& l){
if (l.isInteger()) q.push_back(l.getInteger());
else {
for (auto& x : l.getList())
dfs(x);
}
}
int next() {
return q[k ++ ];
}
bool hasNext() {
return k < q.size();
}
};
/**
* Your NestedIterator object will be instantiated and called as such:
* NestedIterator i(nestedList);
* while (i.hasNext()) cout << i.next();
*/
1497. 树的遍历(3月23日)
分析
直接用unordered_map>
建左子树, 右子树
注意build
的时候 需要判断il < k
ir > k
code
#include <iostream>
#include <unordered_map>
#include <queue>
using namespace std;
const int N = 40;
int posterorder[N], inorder[N];
unordered_map<int, int> l, r, pos;
int build(int il, int ir, int pl, int pr){
int root = posterorder[pr];
int k = pos[root];
if (il < k) l[root] = build(il, k - 1, pl, pl + (k - 1 - il));
if (ir > k) r[root] = build(k + 1, ir, pl + (k - 1 - il) + 1, pr - 1);
return root;
}
void bfs(int root){
queue<int> q;
q.push(root);
while (q.size()){
auto t = q.front(); q.pop();
cout << t << ' ';
if (l.count(t)) q.push(l[t]);
if (r.count(t)) q.push(r[t]);
}
}
int n;
int main(){
scanf("%d", &n);
for (int i = 0; i < n; i ++ ) scanf("%d", &posterorder[i]);
for (int i = 0; i < n; i ++ ){
scanf("%d", &inorder[i]);
pos[inorder[i]] = i;
}
int root = build(0, n - 1, 0, n - 1);
bfs(root);
return 0;
}
LeetCode 456. 132模式(3月24日)
分析
第1步还是要去想, 怎么样去枚举, 能够把答案枚举出来
当然最暴力的, 枚举i, j, k, 时间复杂度O(n^3)
考虑下怎么优化.
优化的时候, 枚举a[i]
, 对于每个a[i]
, 判断a[i]
的后面, 是否存在a[k]
满足要求
满足要求的话, 那么返回true
如果对于a[i]
不存在任何满足要求的数, 使得132成立的话, 再去枚举前面的a[i]
这样的话, 如果存在132的话, 一定可以将答案枚举出来
然后看下, 对于每个a[i]
, 怎么能够快速的判断, 后面是否存在满足要求的a[j]
, a[k]
如果a[k]
满足要求, 那么a[i]
后面, 最大的a[k]
也必然比a[i]
要大, 也就是说对于每个a[i]
, 我们只需要求出来后面满足要求最大的a[k]
栈里面保存的是所有未满足要求的a[k]
然后我们可以寻找图中圈出来的部分, 这部分是满足要求的, 用right
记录最大值
所以倒序遍历的时候, 只需要判断right > nums[i]
就可以了
right 维护的是潜在的a[k]
, 因为可以通过单调栈维护a[k]
当栈顶元素<当前数
nums[i]
的时候, 那么栈顶元素就是潜在的a[k]
, 因此可以边删边维护, 那么栈里剩下就全部是不满足要求的数了
code
class Solution {
public:
bool find132pattern(vector<int>& nums) {
stack<int> stk;
int right = INT_MIN;
for (int i = nums.size() - 1; i >= 0; i -- ){
if (nums[i] < right) return true;
while (stk.size() && stk.top() < nums[i]){
right = max(right, stk.top());
stk.pop();
}
stk.push(nums[i]);
}
return false;
}
};
131. 直方图中最大的矩形(3月24日)
分析
考虑i左边哪些数可以作为答案输出
如果a[x] >= a[y], 假设a[x]可以作为答案被输出, 会矛盾
因为a[x]可以作为答案输出的话, 表示a[x]是<= i的距离i最近的数, 但是a[x] >= a[y], 那么a[y] 也是<= i的距离i最近的数, 因此答案必定是a[y]
这样就证明了可以作为答案输出的数, 一定不存在逆序关系, 必定是单调上升的
那么可以用栈来维护左边可以作为答案的数
每次来了一个新数a[i]
之后, 我们首先要找到左边比a[i]
小的数, 直接在所有可以作为答案的集合里去找就可以了
因为要找的数是比a[i]小的数, 那么所有>= a[i]的数一定不是答案
而且我们, 可以发现
删完之后, 再把a[i]
插入, 整个序列还是单调递增的
code
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 100010;
int n;
int h[N], l[N], r[N], q[N];
int main()
{
while (scanf("%d", &n), n)
{
for (int i = 1; i <= n; i ++ ) scanf("%d", &h[i]);
h[0] = h[n + 1] = -1;
int tt = 0; // 初始栈下标设置为0
q[0] = 0; // 左边界设置为0
for (int i = 1; i <= n; i ++ )
{
while (h[i] <= h[q[tt]]) tt -- ;
l[i] = q[tt];
q[ ++ tt] = i;
}
tt = 0; // 初始栈下标设置为0
q[0] = n + 1; // 右边届设置为n + 1
for (int i = n; i; i -- )
{
while (h[i] <= h[q[tt]]) tt -- ;
r[i] = q[tt];
q[ ++ tt] = i;
}
LL res = 0;
for (int i = 1; i <= n; i ++ )
res = max(res, (LL)h[i] * (r[i] - l[i] - 1));
printf("%lld\n", res);
}
return 0;
}
LeetCode 82. 删除排序链表中的重复元素 II
分析
新建一个q
变量, 记录p->next->next
, 然后每次比较p->next
与q
的值
code
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
auto dummy = new ListNode(-1);
dummy->next = head;
auto p = dummy;
while (p->next) {
auto q = p->next->next;
while (q && q->val == p->next->val) q = q->next;
if (p->next->next == q) p = p->next;
else p->next = q;
}
return dummy->next;
}
};