LeetCode 136,141,155,160,169,206

LeetCode 136 只出现一次的数字 简单
一次异或就得出结果

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int n=nums.size();
        int x=0;
        for(int i=0;i<n;i++){
            x^=nums[i];
        }
        return x;
    }
};

LeetCode 141 环形链表 简单
用快慢指针就可以了,注意对空指针的处理

class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode* fast=head;
        ListNode* slow=head;
        while(fast!=nullptr){
            fast=fast->next;
            if(fast!=nullptr){
                fast=fast->next;
            }
            if(fast==slow) return true;
            slow=slow->next;
        }
        
        return false;
    }
};

LeetCode 155 最小栈 简单
用栈实现栈也是让人没想到的
自己写的

class MinStack {
    stack<int> stk;
    stack<int> min_stk;
public:
    /** initialize your data structure here. */
    
    MinStack() {
        min_stk.push(INT_MAX);
    }
    
    void push(int x) {
        stk.push(x);
        if(x<min_stk.top()){
            min_stk.push(x);
        }
        else{
            int p=min_stk.top();
            min_stk.pop();
            min_stk.push(x);
            min_stk.push(p);
        }
    }
    
    void pop() {
        int p=stk.top();
        stk.pop();
        int count=0;
        while(p!=min_stk.top()){
            stk.push(min_stk.top());
            min_stk.pop();
            count++;
        }
        min_stk.pop();
        while(count>0){
            min_stk.push(stk.top());
            stk.pop();
            count--;
        }
    }
    
    int top() {
        return stk.top();
    }
    
    int getMin() {
        return min_stk.top();
    }
};

题解

class MinStack {
    stack<int> x_stack;
    stack<int> min_stack;
public:
    MinStack() {
        min_stack.push(INT_MAX);
    }
    
    void push(int x) {
        x_stack.push(x);
        min_stack.push(min(min_stack.top(), x));
    }
    
    void pop() {
        x_stack.pop();
        min_stack.pop();
    }
    
    int top() {
        return x_stack.top();
    }
    
    int getMin() {
        return min_stack.top();
    }
};

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/min-stack/solution/zui-xiao-zhan-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

把栈最小值和当前值组对保存。

class MinStack {
    stack<pair<int,int>> stk;
public:
    /** initialize your data structure here. */
    
    MinStack() {
        
    }
    
    void push(int x) {
        if(stk.size()==0) stk.push({x,x});
        else stk.push({x,min(x,stk.top().second)});
        
    }
    
    void pop() {
        stk.pop();
        
    }
    
    int top() {
        return stk.top().first;
    }
    
    int getMin() {
        return stk.top().second;
    }
};

160 相交链表 简单
1.哈希表查找

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        unordered_set<ListNode*> s;
        while(headA!=nullptr){
            s.insert(headA);
            headA=headA->next;
        }
        while(headB!=nullptr){
            if(s.find(headB)!=s.end()){
                return headB;
            }
            headB=headB->next;
        }
        return nullptr;
    }
};

2.双指针法,pA遍历完指向另一列的头,pB同样操作,直到相遇。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *a = headA, *b = headB;
        while(a != b)
        {
            if(a==nullptr){
                a=headB;
            }
            else{
                a=a->next;
            }
            if(b==nullptr){
                b=headA;
            }
            else{
                b=b->next;
            }
        }
        return a;
    }

};

169 多数元素 简单
1.用map记录元素出现的次数,在遍历map找出现最多的数

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        map<int,int> mp;
        int res;
        for(auto &n:nums){
            mp[n]++;
            if(mp[n]>nums.size()/2){
                res=n;
                break;
            }
        }
        return res;
    }
};
  1. 排序,找第n/2个元素
class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int n=nums.size();
        sort(nums.begin(),nums.end());
        return nums[n/2];
    }
};

方法五:Boyer-Moore 投票算法
思路

如果我们把众数记为 +1+1,把其他数记为 -1−1,将它们全部加起来,显然和大于 0,从结果本身我们可以看出众数比其他数多。

算法

Boyer-Moore 算法的本质和方法四中的分治十分类似。我们首先给出 Boyer-Moore 算法的详细步骤:

我们维护一个候选众数 candidate 和它出现的次数 count。初始时 candidate 可以为任意值,count 为 0;

我们遍历数组 nums 中的所有元素,对于每个元素 x,在判断 x 之前,如果 count 的值为 0,我们先将 x 的值赋予 candidate,随后我们判断 x:

如果 x 与 candidate 相等,那么计数器 count 的值增加 1;

如果 x 与 candidate 不等,那么计数器 count 的值减少 1。

在遍历完成后,candidate 即为整个数组的众数。

我们举一个具体的例子,例如下面的这个数组:

[7, 7, 5, 7, 5, 1 | 5, 7 | 5, 5, 7, 7 | 7, 7, 7, 7]
在遍历到数组中的第一个元素以及每个在 | 之后的元素时,candidate 都会因为 count 的值变为 0 而发生改变。最后一次 candidate 的值从 5 变为 7,也就是这个数组中的众数。

Boyer-Moore 算法的正确性较难证明,这里给出一种较为详细的用例子辅助证明的思路,供读者参考:

首先我们根据算法步骤中对 count 的定义,可以发现:在对整个数组进行遍历的过程中,count 的值一定非负。这是因为如果 count 的值为 0,那么在这一轮遍历的开始时刻,我们会将 x 的值赋予 candidate 并在接下来的一步中将 count 的值增加 1。因此 count 的值在遍历的过程中一直保持非负。

那么 count 本身除了计数器之外,还有什么更深层次的意义呢?我们还是以数组

[7, 7, 5, 7, 5, 1 | 5, 7 | 5, 5, 7, 7 | 7, 7, 7, 7]
作为例子,首先写下它在每一步遍历时 candidate 和 count 的值:

nums: [7, 7, 5, 7, 5, 1 | 5, 7 | 5, 5, 7, 7 | 7, 7, 7, 7]
candidate: 7 7 7 7 7 7 5 5 5 5 5 5 7 7 7 7
count: 1 2 1 2 1 0 1 0 1 2 1 0 1 2 3 4
我们再定义一个变量 value,它和真正的众数 maj 绑定。在每一步遍历时,如果当前的数 x 和 maj 相等,那么 value 的值加 1,否则减 1。value 的实际意义即为:到当前的这一步遍历为止,众数出现的次数比非众数多出了多少次。我们将 value 的值也写在下方:

nums: [7, 7, 5, 7, 5, 1 | 5, 7 | 5, 5, 7, 7 | 7, 7, 7, 7]
value: 1 2 1 2 1 0 -1 0 -1 -2 -1 0 1 2 3 4
有没有发现什么?我们将 count 和 value 放在一起:

nums: [7, 7, 5, 7, 5, 1 | 5, 7 | 5, 5, 7, 7 | 7, 7, 7, 7]
count: 1 2 1 2 1 0 1 0 1 2 1 0 1 2 3 4
value: 1 2 1 2 1 0 -1 0 -1 -2 -1 0 1 2 3 4
发现在每一步遍历中,count 和 value 要么相等,要么互为相反数!并且在候选众数 candidate 就是 maj 时,它们相等,candidate 是其它的数时,它们互为相反数!

为什么会有这么奇妙的性质呢?这并不难证明:我们将候选众数 candidate 保持不变的连续的遍历称为「一段」。在同一段中,count 的值是根据 candidate == x 的判断进行加减的。那么如果 candidate 恰好为 maj,那么在这一段中,count 和 value 的变化是同步的;如果 candidate 不为 maj,那么在这一段中 count 和 value 的变化是相反的。因此就有了这样一个奇妙的性质。

这样以来,由于:

我们证明了 count 的值一直为非负,在最后一步遍历结束后也是如此;

由于 value 的值与真正的众数 maj 绑定,并且它表示「众数出现的次数比非众数多出了多少次」,那么在最后一步遍历结束后,value 的值为正数;

在最后一步遍历结束后,count 非负,value 为正数,所以它们不可能互为相反数,只可能相等,即 count == value。因此在最后「一段」中,count 的 value 的变化是同步的,也就是说,candidate 中存储的候选众数就是真正的众数 maj。

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int candidate = -1;
        int count = 0;
        for (int num : nums) {
            if (num == candidate)
                ++count;
            else if (--count < 0) {
                candidate = num;
                count = 1;
            }
        }
        return candidate;
    }
};

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/majority-element/solution/duo-shu-yuan-su-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  1. 反转链表 简单
    迭代
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(head==nullptr) return nullptr;
        if(head->next==nullptr) return head;
        ListNode* pre=nullptr;
        ListNode* cur=head;
        ListNode* next=head->next;
        while(next!=nullptr){
            cur->next=pre;
            pre=cur;
            cur=next;
            next=next->next;

        }
        cur->next=pre;
        return cur;
    }
};

递归

class Solution {
public:

    ListNode* reverseList(ListNode* head) {
        if(head==nullptr) return nullptr;
        if(head->next==nullptr) return head;
        ListNode* newHead=reverseList(head->next);
        head->next->next=head;
        head->next=nullptr;
        return newHead;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值