偷懒回来了

最近放假,翻翻七月似乎只更了一篇文章,转眼就到了八月了…
实在是松懈了很多啊,最近调理了一下心情,暑假埋头于学英语和计网…数据结构和算法也是放下了好一阵子,然后下定决心卸载了游戏,终于重新开始坚持刷题。
前路很难,时常会让我绝望,压的我几乎不能呼吸,但总会有微弱的光指引着我前进。
好了不多说废话,这两天在leetcode上随意刷了些题。发现我的动态规划已经差的一塌糊涂
今天更一些最近刷的题目。

495. 提莫攻击
在《英雄联盟》的世界中,有一个叫 “提莫” 的英雄,他的攻击可以让敌方英雄艾希(编者注:寒冰射手)进入中毒状态。现在,给出提莫对艾希的攻击时间序列和提莫攻击的中毒持续时间,你需要输出艾希的中毒状态总时长。
你可以认为提莫在给定的时间点进行攻击,并立即使艾希处于中毒状态。
示例1:
输入: [1,4], 2
输出: 4
原因: 在第 1 秒开始时,提莫开始对艾希进行攻击并使其立即中毒。中毒状态会维持 2 秒钟,直到第 2 秒钟结束。
在第 4 秒开始时,提莫再次攻击艾希,使得艾希获得另外 2 秒的中毒时间。
所以最终输出 4 秒。
示例2:
输入: [1,2], 2
输出: 3
原因: 在第 1 秒开始时,提莫开始对艾希进行攻击并使其立即中毒。中毒状态会维持 2 秒钟,直到第 2 秒钟结束。
但是在第 2 秒开始时,提莫再次攻击了已经处于中毒状态的艾希。
由于中毒状态不可叠加,提莫在第 2 秒开始时的这次攻击会在第 3 秒钟结束。
所以最终输出 3。
注意:
你可以假定时间序列数组的总长度不超过 10000。
你可以假定提莫攻击时间序列中的数字和提莫攻击的中毒持续时间都是非负整数,并且不超过 10,000,000。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/teemo-attacking
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这题,难度比较迷,我觉得连很多简单都不如。。当然也是两遍ac了,之所以是两遍,是因为第一遍没考虑数组为空的状态。水题。

class Solution {
    public int findPoisonedDuration(int[] timeSeries, int duration) {
        if(timeSeries.length == 0) return 0;
        int res = duration;
        for(int i = 1; i < timeSeries.length; i ++) {
            if(timeSeries[i] - timeSeries[i - 1] >= duration) 
                res += duration;
            else res += timeSeries[i] - timeSeries[i - 1];
        }
        return res;
    }
}

217. 存在重复元素
给定一个整数数组,判断是否存在重复元素。
如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。
示例 1:
输入: [1,2,3,1]
输出: true
示例 2:
输入: [1,2,3,4]
输出: false
示例 3:
输入: [1,1,1,3,3,4,3,2,4,2]
输出: true
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/contains-duplicate
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

看一下这题,是简单,最起码的都可以用数组来标记了。我一开始用了hashmap

class Solution {
    public boolean containsDuplicate(int[] nums) {
        Map<Integer, Integer> map = new HashMap<>();
        for(int num : nums) {
            int count = map.getOrDefault(num, 0) + 1;
            map.put(num, count);
            if(count >= 2)
                return true;
        }
        return false;
    }
}

一遍ac了,只是击败的人数有点惨,连百分之二十也不到。
然后看了一下评论,有用排序的,然后遍历一遍看相邻有无相同的,排序速度在o(nlogn)
然后查询遍历一次在o(n)。
我个人觉得会麻烦。
有一个更棒的方法,用set,直接把每一个数字加入set里,set自己的特性会去重。于是,如果set的长度和原本的不一样的话,那就是有重复咯.

class Solution {
    public boolean containsDuplicate(int[] nums) {
        int n = nums.length;
        Set<Integer> set = new HashSet<>();
        for(int num : nums) {
            set.add(num);
        }
        return set.size() == nums.length ? false : true;
    }
}

然后遇到一个稍微有意思的题目。
397. 整数替换
给定一个正整数 n,你可以做如下操作:
1. 如果 n 是偶数,则用 n / 2替换 n。
2. 如果 n 是奇数,则可以用 n + 1或n - 1替换 n。
n 变为 1 所需的最小替换次数是多少?
示例 1:
输入:
8
输出:
3
解释:
8 -> 4 -> 2 -> 1
示例 2:
输入:
7
输出:
4
解释:
7 -> 8 -> 4 -> 2 -> 1

7 -> 6 -> 3 -> 2 -> 1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/integer-replacement
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这个稍微有点题感的第一眼就是递归咯。
于是直接码了一发,结果最后一个测试数据错了,因为没考虑到边界数据,也就是最大的int整数。
改了一下ac于是就没去想dp的方法了。

class Solution {
    public int integerReplacement(int n) {
        if(n == 1) return 0;
        if(n == 2147483647) return 32;
        return dfs(n, 0);
    }
    public int dfs(int n, int ans) {
        if(n == 1)
            return ans;
        if((n & 1) != 1) {
            return dfs(n / 2, ans + 1);
        }
        else return Math.min(dfs(n + 1, ans + 1), dfs(n - 1, ans + 1));
    }
}

效率也是一般般,毕竟暴力递归快不到哪去。

494. 目标和
给定一个非负整数数组,a1, a2, …, an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。
返回可以使最终数组和为目标数 S 的所有添加符号的方法数。
示例 1:
输入: nums: [1, 1, 1, 1, 1], S: 3
输出: 5
解释:
-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3
一共有5种方法让最终目标和为3。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/target-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

emm我直接偷懒又用了递归,好吧,我错了,我以后一定要考虑更优解。
其实和上面一题也差不多把…
直接暴力ac了…

class Solution {
    public int findTargetSumWays(int[] nums, int S) {
        return dfs(nums, S, 0, nums.length);
    }
    public int dfs(int[] nums, int S, int index, int len) {
        if(S == 0 && index == len) 
            return 1;
        if(S != 0 && index == len)
            return 0;
        int x = dfs(nums, S - nums[index], index + 1, len);
        int y = dfs(nums, S + nums[index], index + 1, len);
        return x + y;
    }
}

我还想存一下状态来着。。。。

209. 长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。
示例:
输入: s = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。
进阶:
如果你已经完成了O(n) 时间复杂度的解法, 请尝试 O(n log n) 时间复杂度的解法。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-size-subarray-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这题乍一看是动态规划。好像确实也可以,但是偷懒的我依然没有动态规划。
试了一下暴力解,三个循环。时间复杂度大概在o(n^3),超时。
于是换方法,用滑动窗口,说白了就是双指针。一个指针一直走。如果满足了>=s的条件后面的指针就前进,吐出来一个数字。但是不管怎么走,我们都保留了一个值来记录最小的长度。

class Solution {
    public int minSubArrayLen(int s, int[] nums) {
        if(nums.length == 0) return 0;
        int start = 0;
        int end = 0;
        int sum = 0;
        int ans = 0x7fffffff;
        while(end < nums.length) {
            sum += nums[end];
            end ++;
            while(sum >= s) {
                sum -= nums[start];
                start += 1;
                 ans = Math.min(ans, end - start + 1);
            }
           
        }
        return ans == 0x7fffffff ? 0 : ans;
    }
}

效率应该还行。

写的比较随意了,完全当作学习笔记了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值