leetCode刷题之贪心算法(3)

leetCode 763 划分字母区间

https://leetcode-cn.com/problems/partition-labels/
题目描述:

字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,
同一个字母只会出现在其中的一个片段。返回一个表示每个字符串片段的长度的列表。
样例:
输入: S = "ababcbacadefegdehijhklij"
输出: [9,7,8]
解释:
划分结果为 "ababcbaca", "defegde", "hijhklij"。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 的划分是错误的,因为划分的片段数较少。

思路
首先很容易想到暴力的O(n^3)的解法,但是肯定会超时,这里有一种O(n)的解法。因为对于当前位置的字母来说,他出现的最后的位置肯定是划分的片段的子集,因为他现在的位置到他最后出现的位置之间的其他字符可能会在之后出现,所以如果说当前位置的字符出现的最后位置就是当前位置,那么就表示这可以划分为一个片段,因为之前的所有字符没有在当前位置之后出现,所以只需要一个charindex的数组记录每个字符出现的最后位置,for循环遍历一次即可实现,空间复杂度为O(n).
实现代码如下:

class Solution {
    public List<Integer> partitionLabels(String S) {
		int len = S.length();
		int[] charindex = new charindex[26];
		for(int i = 0;i < len;i++)
			charindex[S.charAt(i)-'a']  = i;
		int j = 0,lastlen = 0;
		List<Integer> ans = new ArrayList<Integer>(); 
		for(int i = 0;i < len;i++){
			j = Math.max(j,charindex[S.charAt(i)]);
			if(i == j){
				ans.add(i-lastlen+1);
				lastlen = i+1;
			}
		}
		return ans;
	}
}

leetCode 55 跳跃游戏

https://leetcode-cn.com/problems/jump-game/
题目描述:

给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个位置。
样例:
输入: [2,3,1,1,4]
输出: true
解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。

思路:
1.首先我们可以用动态规划的思想来考虑这个问题,使用一个dp数组,对于当前位置来说,如果可以从当前位置出发,将当前位置可以到达的位置dp[]值都设为1,循环遍历整个数组,最终如果终点的dp值为1,那么输出true,这个方法时间复杂度较高,最坏情节为O(N^2),这个方法是可以进行优化的,这里就不说了
2.一种简单的方法是可以用贪心的方法来求解这道题,首先对于最后的位置target来说,从后向前遍历,如果当前位置nums[i]+i >= target ,这说明当前位置可以到达最后的位置,这个时候只要能到达当前位置,就肯定可以到达最后位置,更新target为i,向前遍历,如果最终target == 0,那说明是可以从起点跳到终点的。
下面给出方法二的代码:

class Solution {
    public boolean canJump(int[] nums) {
        int len = nums.length;
        int target = len-1;
        for(int i = len-2;i>=0;i--){
            if(nums[i]+i >= target){
                target = i;
            }
        }
        return target == 0;
    }
}

leetCode 45 跳跃游戏II

https://leetcode-cn.com/problems/jump-game-ii/
题目描述:

给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
输入: [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
     从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

思路
延续上一道题LeetCode55 的思路,这次我们找跳跃的最少次数,这个时候我们可以每一次跳跃都跳到下一跳的距离最大的位置上,这保证我们可以跳动更远,那么就可以达到一个局部最优解,直到全局最优解。
代码如下:

class Solution {
    public int jump(int[] nums) {
		int min = 0;
		int maxp = 0;
		int end = 0;
		for(int i = 0;i < nums.length-1;i++){
			maxp = Math.max(maxp,nums[i]+i);//每次更新当前范围内所能到达的最大位置
			if(i == end){ //当到达边界值时,更新边界值,并min+1
				end = maxp;
				min++;
			}
		}
		return min;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值