★leetcode45_Jump Game II

一.问题描述

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Your goal is to reach the last index in the minimum number of jumps.

For example:
Given array A = [2,3,1,1,4]

The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.)

找到由第一个元素到最后一个元素所需的最小跳数,在每个位置上能跳的最大步数不超高当前位置的元素值。


二.代码编写

看完题目我很快就想到思路,还觉得这题一点都不hard,结果TLE了,看完真正大神的解法,才觉得自己的代码真是搓搓的。搓到不想说的算法思路,不愿意贴代码。。。

'''
@ author: wttttt at 2016.11.25
@ problem description see: https://leetcode.com/problems/jump-game-ii/
@ solution explanation see: http://blog.csdn.net/u014265088/article/details/53337157
@ github:https://github.com/wttttt-wang/leetcode
@ data_structure/deque
@ Time Limit Exceeded
  time complexity can be very large when elements in nums is large.
@ another TLE solution is dp, x[i] = min(x[k]) + 1 where 0<=k<i and A[k] >= i-k
  time complexity is O(N^2)
@ for better solution, see ../../greedy/45JumpGameII
'''
from collections import deque

class Solution(object):
    def if_exists(self, dq, value):
        '''
        check that if there exists the target value
        '''
        for i in dq:
            if i == value:
                return True
        return False

    def jump(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        len_nums = len(nums)
        if len_nums == 1:
            return 0
        # point_rnum = 0 # the pointer to indicate how many jumps now
        point_list = 0  # the pointer to indicate
        rnum = 0  # the return jump nums
        list_queue = deque([0])
        while list_queue != None:
            x = list_queue.popleft()
            for i in range(nums[x]):
                y = x+i+1
                if y == len_nums - 1:
                    return rnum+1
                if self.if_exists(list_queue, y) == False:
                    list_queue.append(y)
            if x == point_list and list_queue != None:
                rnum += 1
                point_list = list_queue[-1]
so = Solution()
# nums = [2,3,1,1,4]
#nums = [1,3,2,2,0,2]
nums = [1,3,2,5,1,1,2]
print so.jump(nums)
我居然是对每一个可能的位置,把该位置可能的跳到的pos记录下来(这太渣了,对大小为M的元素还不得记录M次啊,,)。这个真的很挫啊,只要nums里面的数数值比较大,肯定TLE啊。

然后想优化一下就想用dp,倒序记录每个位置到最后一个位置所需的最小跳数,时间复杂度O(N^2),实际上这个思路并不比我上面那个solution好,不过至少听起来有点算法的思想这。。。个代码我没实现,因为百度了一下发现用这个思想还是TLE- -

三.算法优化

然后我又偷看了下tags,看到提示说用greedy,然后我一想greedy不就是每次选择当前最优解嘛,于是我就思考能不能每次都跳最大个数,然后我就马上想到了下面这种情况:

nums = [1,3,2,5,1,1,2]
很明显对这种情况greedy会取到局部最优解,所以严格意义上来讲这并不是一道greddy能解的题嘛,所以我觉得leetcode给的tags很坑,以后不能偷看!!!

但是最后解法还是要用到了greedy的思想,你想虽然我们不能直接jump到最大下一跳,但是我们可以把下一跳的位置存下来。

这个解法的具体思路就是维护一个区间,区间里是当前跳数能达到的pos范围。每一跳,取区间内的元素可以跳到的最大位置+1作为下一次的区间。

具体代码如下:

'''
@ author: wttttt at 2016.11.25
@ problem description see: https://leetcode.com/problems/jump-game-ii/
@ solution explanation see: http://blog.csdn.net/u014265088/article/details/53337157
@ github:https://github.com/wttttt-wang/leetcode
@ greedy, but not restrict greedy, for that we save the interval rather than jump directly.
@ maintain an interval for each step's reach range
   the interval's left edge is last interval's right edge;
   the interval's right edge is the maximum pos that last interval's elements can reach.
@ time complexity: O(N), space complexity O(1)
'''

class Solution(object):
    def jump(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        len_nums = len(nums)
        if len_nums == 1:
            return 0
        '''
        initialize the interval
        note that right is the current interval's right edge's next element
        '''
        left = 0
        before_right = 1
        right = 1
        rnum = 0  # the return num
        while True:
            for i in range(left,right):  # iterate on current interval's elements
                y = (nums[i]+i+1)
                if y >=len_nums:
                    return rnum+1
                if y > right:
                    right = y   # find the maximum edge that the current step can reach
            left = before_right
            before_right = right
            rnum += 1

so = Solution()
nums = [2,3,1,1,4]
#nums = [1,3,2,2,0,2]
#nums = [1,3,2,5,1,1,2]
print so.jump(nums)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题目描述: 给定一个字符串,请将字符串里的字符按照出现的频率降序排列。 示例 1: 输入: "tree" 输出: "eert" 解释: 'e'出现两次,'r'和't'都只出现一次。因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。 示例 2: 输入: "cccaaa" 输出: "cccaaa" 解释: 'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。注意"cacaca"是不正确的,因为相同的字母必须放在一起。 示例 3: 输入: "Aabb" 输出: "bbAa" 解释: 此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。注意'A'和'a'被认为是两种不同的字符。 Java代码如下: ``` import java.util.*; public class Solution { public String frequencySort(String s) { if (s == null || s.length() == 0) { return ""; } Map<Character, Integer> map = new HashMap<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); map.put(c, map.getOrDefault(c, 0) + 1); } List<Map.Entry<Character, Integer>> list = new ArrayList<>(map.entrySet()); Collections.sort(list, (o1, o2) -> o2.getValue() - o1.getValue()); StringBuilder sb = new StringBuilder(); for (Map.Entry<Character, Integer> entry : list) { char c = entry.getKey(); int count = entry.getValue(); for (int i = 0; i < count; i++) { sb.append(c); } } return sb.toString(); } } ``` 解题思路: 首先遍历字符串,使用HashMap记录每个字符出现的次数。然后将HashMap转换为List,并按照出现次数从大到小进行排序。最后遍历排序后的List,将每个字符按照出现次数依次添加到StringBuilder中,并返回StringBuilder的字符串形式。 时间复杂度:O(nlogn),其中n为字符串s的长度。遍历字符串的时间复杂度为O(n),HashMap和List的操作时间复杂度均为O(n),排序时间复杂度为O(nlogn),StringBuilder操作时间复杂度为O(n)。因此总时间复杂度为O(nlogn)。 空间复杂度:O(n),其中n为字符串s的长度。HashMap和List的空间复杂度均为O(n),StringBuilder的空间复杂度也为O(n)。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值