令人头秃的LeetCode——141. 环形链表

题目链接:141. 环形链表


解法一 暴力法(哈希表)

思路

  • 遍历链表,利用哈希表存储指针指向节点的地址。
  • 判断指针指向节点的地址是否在哈希表中存在,若存在,直接返回true,否则,指针向后移动,继续遍历。
  • 若指针指向空,返回false。
	public boolean hasCycle(ListNode head) {
        ListNode cur = head;
        HashSet<ListNode> set = new HashSet<>();
        while (!set.contains(cur) && cur != null){
            set.add(cur);
            cur = cur.next;
        }
        return cur != null;
    }

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(n),建立了哈希表,开辟了额外空间

解法二 双指针(快慢指针)

思路

快慢指针,可以理解为两个速度不一样的运动员在沿着环形跑道追赶。

假设跑道长度为 N N N ,运动员A的速度为 x x x ,运动员B的速度为 y y y ,运动员B起点比运动员A靠前 k k k 个单位长度,两者同时出发,最终能够相遇吗?答案是肯定的,只需要满足等式 y T = x T + N − k yT = xT + N - k yT=xT+Nk,式子表示 T T T 时刻两者相遇。

具体的,我们令 x = 1 , y = 2 x = 1, y = 2 x=1y=2,代入上式,可求得相遇时间 T = N − k T = N - k T=Nk

  • 初始化双指针,并定义起点位置,快慢指针的速度分别为2和1。
  • 若链表中存在环,则两指针必定相遇,若不存在,则需要注意快指针是否已经指向空。
	public boolean hasCycle(ListNode head) {
        if (head == null)
            return false;
        ListNode slow = head;
        ListNode fast = head.next;
        while (slow != fast){
            if (fast == null || fast.next == null)
                return false;
            fast = fast.next.next;
            slow = slow.next;
        }
        return true;
    }

复杂度分析

  • 时间复杂度:
    • 若链表不存在环,时间复杂度为O(n)
    • 若链表存在环,环的长度为N,非环部分为M,则在非环部分首先迭代了M次。接着,进入环部分,假设此时快指针领先k个单位长度,k的取值范围为[0, N],则进行(N - k)次迭代,一共迭代(M + N - K)次,时间复杂度为O(M + N - K),即为O(n)
    • 综上,时间复杂度为O(n)
  • 空间复杂度:O(1)

小结

对付链表,直观的三个思路:

  • 单指针(暴力法,直观,但浪费点空间)
  • 双指针(省空间,思路略复杂,骚操作比较多)
  • 递归(毕竟链表结构是递归的,Emmmm~但是难想)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
解释: 1. self.epsilon = 0.1 if e_greedy_increment is not None else self.epsilon_max: 这行代码是用来设置epsilon的值。epsilon是用于控制在强化学习中探索和利用之间的平衡。如果e_greedy_increment不为None,即存在增量值,那么epsilon的初始值为0.1;否则,epsilon的初始值为self.epsilon_max。 2. self.lr_decay_rate = 0.95和self.lr_decay_step = 10000: 这两行代码是用于定义学习率的衰减速率和衰减步数。学习率衰减是为了让模型在训练过程中逐渐降低学习率,以便更好地收敛到最优解。在这里,学习率以指数衰减的方式进行更新,每经过10000个步骤,学习率会以0.95的衰减速率进行衰减。 3. self.lr = tf.train.exponential_decay(self.learning_rate, self.global_step, self.lr_decay_step, self.lr_decay_rate, staircase=True): 这行代码定义了学习率的指数衰减方式。tf.train.exponential_decay函数用于计算学习率的衰减值。其中,learning_rate是初始学习率,global_step是当前训练步数,lr_decay_step是衰减步数,lr_decay_rate是衰减速率,staircase=True表示学习率以阶梯函数的形式进行衰减。 4. self.l_r = self.learning_rate: 这行代码将初始学习率赋值给l_r,可能用于后续的学习率更新。 5. self.gama = 3、self.tau = 0.5和self.r_base = [0]: 这三行代码定义了一些参数。gama是拉格朗日乘子,用于某些优化问题中的约束条件;tau是计算reward滑动平均的参数,用于平滑reward的变化;r_base是一个包含单个元素0的列表,可能用于存储reward的基准值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值