Week2

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->nextq的值

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;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值