LeetCode刷题之贪心算法(2)

LeetCode 605 种花问题

https://leetcode-cn.com/problems/can-place-flowers/
题目描述:

假设你有一个很长的花坛,一部分地块种植了花,另一部分却没有。
可是,花卉不能种植在相邻的地块上,它们会争夺水源,两者都会死去。
给定一个花坛(表示为一个数组包含0和1,其中0表示没种植花,1表示种植了花),
和一个数 n 。能否在不打破种植规则的情况下种入 n 朵花?
能则返回True,不能则返回False。

输入: flowerbed = [1,0,0,0,1], n = 1
输出: True
输入: flowerbed = [1,0,0,0,1], n = 2
输出: False
* 数组内已种好的花不会违反种植规则。
* 输入的数组长度范围为 [1, 20000]。
* n 是非负整数,且不会超过输入数组的大小。

思路
对于这道题来说,因为已经种好的花不会违反种植规则,所以对于每一个1,都有紧跟的0位置,可以跳过,所以,当当前位置值为1时,i = i+2;
而当当前位置为0时,前面肯定是0或者是起始位置,所以只需要看下一个位置的值,这个时候有一个临界条件,如果当前位置是数组末尾,此时是可种植的,如果不是,那么就需要看下一个位置的值,若是0,则可以种植,此时 i=i+2,若是1,则不能种植, i = i+1,到下一个位置。
代码如下:

class Solution {
    public boolean canPlaceFlowers(int[] flowerbed, int n) {
        int count = 0;
        int len = flowerbed.length;
        int i = 0;
        while(i < len){
            if(flowerbed[i] == 1){
                i = i+2;
            }
            else {
                if(i == len-1)
                {
                    count++;
                    break;
                }
                if(flowerbed[i+1] == 0){
                    count++;
                    i = i+2;
                }
                else
                    i = i+1;       
            }
        }
        return count>= n;
    }
}

leetcode 392 判断子序列

https://leetcode-cn.com/problems/is-subsequence/
题目描述:

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长
(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符
而不改变剩余字符相对位置形成的新字符串。
(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

思路:这里给出一种复杂度为O(n^2)的动态规划的思想,对于找到s在t中的相应的值,我们可以考虑使用一个dp[s.length()+1][t.length()+1]的数组来存储,dp[i][j] 表示当前长度为i的s序列是不是当前长度为j的t序列的子序列,可以写出一个转移方程:

  • dp[i][j] = dp[i-1][j-1] if s.charAt(i) == t.charAt(j)
  • dp[i][j] = dp[i][j-1] if s.charAt(i) != t.charAt(j)

如果当前的值相同,那么就看dp[i-1][j-1]的值,因为前面序列为子序列的话,那么肯定也是子序列,如果当前值不同,就看dp[i][j-1]的值,对于当前的s序列,长度为j-1的t序列是否包含。

class Solution {
    public boolean isSubsequence(String s, String t) {
        int[][] dp = new int[s.length()+1][t.length()+1];
        for(int j = 0;j <= t.length();j++)
            dp[0][j] = 1;
        for(int i = 1;i <= s.length();i++)
            dp[i][0] = 0;
        for(int i = 1;i <= s.length();i++){
            for(int j = 1; j <= t.length();j++){
                if(s.charAt(i-1) == t.charAt(j-1)){
                    dp[i][j] = dp[i-1][j-1];
                }
                else{
                    dp[i][j] = dp[i][j-1];
                }
            }
        }
        return dp[s.length()][t.length()] == 1;
    }
}

leetCode 665 非递减序列

https://leetcode-cn.com/problems/non-decreasing-array/
题目描述:

给定一个长度为 n 的整数数组,你的任务是判断在最多改变 1 个元素的情况下,
该数组能否变成一个非递减数列。
我们是这样定义一个非递减数列的:
 对于数组中所有的 i (1 <= i < n),满足 array[i] <= array[i + 1]。
样例:
输入: [4,2,3]
输出: True
解释: 你可以通过把第一个4变成1来使得它成为一个非递减数列

思路:这是一道easy难度的题,想了好久才写出来,还是太菜了,需要多加练习啊。是要变化一次,让数组变为递增数组,可以设置一个count 记录变化的次数,变化的次数大于1次,那么说明无法完成。
对于nums[i] < nums[i-1],这说明此时需要变化,才能满足数组递增的要求,有两种情况:

  • i-2 >= 0 && nums[i-2] > nums[i] do nums[i] = nums[i-1]
    {此时nums[i-2] < nums[i-1],nums[i-2] > nums[i],为了保证数组递增且改变一个位置的值,只有改变nums[i]的值才能满足}
  • else nums[i-1] = nums[i]
    {这时,nums[i-2] < nums[i-1] && nums[i-2] < nums[i],nums[i-1] > nums[i],为了满足改变一个位置的值保证数组递增,那么只有改变nums[i-1]的值}
    代码如下:
class Solution {
    public boolean checkPossibility(int[] nums) {
        int count = 0;
        for(int i = 1;i < nums.length;i++){
            if(nums[i] < nums[i-1])
            {
                count++;
                if(i-2 >= 0 && nums[i-2] > nums[i])
                    nums[i] = nums[i-1];
                else
                    nums[i-1] = nums[i];
                if(count > 1)
                    return false;
            }
        }   
        return true;
    }
}

leetCode 53 最大子序和

https://leetcode-cn.com/problems/maximum-subarray/

题目描述:

给定一个整数数组 nums ,找到一个具有最大和的连续子数组
(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

思路
因为是要找到最大和的连续子数组,所以如果之前的序列和小于0的话是不需要加进去的,从当前位置开始可以得到最大的和,所以只需要定义两个变量,循环搜索一次就可以得到最佳的;
代码如下:

class Solution {
    public int maxSubArray(int[] nums) {
		if(nums.length == 1)
			return nums[0];
		int max = nums[0];
		int ans = nums[0];
		for(int i = 1;i < nums.length;i++){
			max = max > 0 ? max+nums[i] : nums[i];
			ans = Math.max(ans,max);	
		}
		return ans;
	}
}
发布了18 篇原创文章 · 获赞 2 · 访问量 387

猜你喜欢

转载自blog.csdn.net/weixin_40907792/article/details/104009860