817. 链表组件「哈希」

思路

暴力

m = nums.length,容易想到一个暴力的方法,记录一个长度为n的布尔数组visit,对于nums中的每个元素,去链表中遍历查找对应的下标i,置对应的visit[i] = true,最后统计有多少个连续的true即可。

时间复杂度为O(nm),估计会超时。

是否存在一个时间复杂度为O(n+m)的方法?

  • 利用哈希表?将链表数据转化为map? 空间复杂度为O(n)

哈希表

根据题目中的已知条件:链表中的元素都是不同的,因此可以遍历一个链表从而做一个映射:value: idx,将其存储在哈希表中。再通过一个上述的visit数组来记录某下标元素是否被访问到。

最后统计visit中有多少个连续的true即可。

代码如下:

/**
 * 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:
    // 暴力:O(nm)
    // 有没有O(n+m)的方法?
    int numComponents(ListNode* head, vector<int>& nums) {
        map<int, int> m;
        
        int n=0;
        ListNode* cur = head;
        while(cur != nullptr){
            m[cur->val] = n++;
            cur = cur->next;
        }
        
        vector<bool> visit(n);
        for (const auto &item : nums){
            visit[m[item]] = true;
        }
        
        int ans = 0;

        for (int i = 0; i < n; ++i) {
            // 统计下降沿的个数
            if ((i==n-1 && visit[i]) || (visit[i] && !visit[i+1])){
                ans++;
            }
        }
        return ans;
    }
};

因为需要额外记录两个内容:mapvisit,所以空间复杂度为O(n)
能否将空间复杂度继续降低呢?

集合

为什么要把链表中的元素做映射呢?遍历链表中元素的时候去nums中判断是否存在不就行了?

nums中的元素存入Set中,后续遍历链表的是否直接判断是否有连续的节点即可。

代码如下:

class Solution {
public:
    int numComponents(ListNode* head, vector<int>& nums) {
        set<int> s;
        for (auto& num :nums){
            s.insert(num);
        }
        
        ListNode* node = head;
        bool flag = false;
        int ans = 0;
        while(node != nullptr){
            //上升沿,前一个元素不在nums中
            if(!flag && s.find(node->val) != s.end()){
                ans++;
                flag = true;
            } else if(s.find(node->val) == s.end()) {
                flag = false;
            }
                
            node = node->next;
        }
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值