leetcode刷题 贪心算法

贪心算法

主要思想:保证每次操作都是局部最优的,并且最后得到的结果是全局最优的

分配饼干

题目描述:https://leetcode.com/problems/assign-cookies/description/

解题思路:每一次发饼干都发给食量最小的孩子,提醒数组要多用指针!

class Solution {
    public int findContentChildren(int[] g, int[] s) {
        if(g.length == 0 || s.length == 0) return 0;
        Arrays.sort(g);
        Arrays.sort(s);
        int gi = 0, si = 0;
        while(gi < g.length && si < s.length) {
        	if(g[gi] <= s[si]) {
        		gi++;
        	}
        	si++;
        }
        return gi;
    }
}

剪绳子

题目描述:https://leetcode-cn.com/problems/jian-sheng-zi-lcof/

解法1:贪心算法, 每一次都最大可能分成乘积最大的

/**
	 * 贪心算法
	 * @param n
	 * @return
	 */
	public int cuttingRope(int n ) {
		if(n < 4) return n - 1;
		int res = 1;
		while(n > 4) {
			res *= 3;
			n = n -3;
		}
		return res * n;
	}

解法2:动态规划 n-1状态的绳子会影响n状态的绳子

/**
	 * 动态规划
	 * @param n
	 * @return
	 */
	public int cuttingRope(int n) {
		int[] dp = new int[n + 1];
		dp[1] = 1;
		dp[2] = 1;
		for(int i = 3; i < n +1; i++) {
			for(int j = 2; j < i; j++) {
				dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j]));
			}
		}
		return dp[n];
		
	}

股票的最大利润

题目描述:https://leetcode-cn.com/problems/gu-piao-de-zui-da-li-run-lcof/

解法1:贪心算法

/**
	 * 贪心算法:每一次都尝试买卖最小的
	 * @param prices
	 * @return
	 */
    public int maxProfit(int[] prices) {
    	int[] sortprices = Arrays.copyOf(prices, prices.length);
    	Arrays.sort(sortprices);

    	int maxProfit = 0;
    	for(int i = 0; i < sortprices.length; i++) {
    		int cur = 0;
    		while(prices[cur]!=sortprices[i]) {
    			cur++;
    		}
    		while(cur < prices.length) {
    			maxProfit = Math.max(maxProfit, prices[cur] - sortprices[i]);
    			cur++;
    		}
    	}
    	if(maxProfit < 0) return 0;
    	return maxProfit;
    	
    }

解法2:动态规划

/**
     * 动态规划
     * 每一天的最大利润就是上一状态
     * @param prices
     * @return
     */
    
    public int maxProfit2(int[] prices) {
    	int[] dp = new int[prices.length];
    	dp[0] = 0;
    	for(int i = 1; i < prices.length; i++) {
    		int minprice = prices[0];
    		for(int j = 0; j < i; j++) {
    			minprice = Math.min(minprice, prices[j]);
    		}
    		dp[i] = Math.max(dp[i -1], prices[i] - minprice);
    	}
    	return dp[dp.length -1];
    }

无重叠子区间

题目描述:https://leetcode-cn.com/problems/non-overlapping-intervals/

解法1:贪心算法

/**
	 * 对题目要求进行等价转化:找出最少移动的重叠区间==找出最大不重叠的区间个数
	 * 
	 * @param intervals
	 * @return
	 */
	public int earseOverlapIntervals(int[][] intervals) {
		if (intervals.length == 0) {
			return 0;
		}
		// 对区间内的右端点进行排序
		Arrays.sort(intervals, new Comparator<int[]>() {

			@Override
			public int compare(int[] interval1, int[] interval2) {
				// TODO Auto-generated method stub
				return interval1[1] - interval2[1];
			}

		});

		int n = intervals.length;
		int right = intervals[0][1];
		int ans = 1;// 区间不重复个数
		for (int i = 1; i < n; i++) {
			// 遍历区间左端点,判断是否大于当前右端点
			// 若大于,则区间不重复
			// 若小于,则区间重复
			if (intervals[i][0] >= right) {
				ans++;
				right = intervals[i][1];
			}
		}
		return n - ans;
	}

解法2:动态规划

public int eraseOverLapIntervals2(int[][] intervals) {
		if (intervals.length == 0) {
			return 0;
		}
		// 对区间内的右端点进行排序
		Arrays.sort(intervals, new Comparator<int[]>() {

			@Override
			public int compare(int[] interval1, int[] interval2) {
				// TODO Auto-generated method stub
				return interval1[1] - interval2[1];
			}

		});
		int n = intervals.length;
		int[] dp = new int[n];
		Arrays.fill(dp, 1);
		for(int i  = 1; i < n; i++) {
			for(int j = 0; j < i ; j++) {
				if(intervals[j][1] <= intervals[i][0]) {
					dp[i] = Math.max(dp[i], dp[j] + 1);
				}
			}
		}
		return n - Arrays.stream(dp).max().getAsInt();
		
		
	}

用最少数量的箭引爆气球

题目描述:https://leetcode-cn.com/problems/minimum-number-of-arrows-to-burst-balloons/

解法:贪心,排序子区间的长度,注意实现compartor接口是,compare方法需要有正负零返回值

class Solution {
    public int findMinArrowShots(int[][] points) {
    	if(points.length == 0) return 0;
    	Arrays.sort(points, new Comparator<int[]>() {
    		@Override
    		public int compare(int[] point1 , int[] point2) {
    			// TODO Auto-generated method stub
    			if (point1[1] > point2[1]) {
                    return 1;
                } else if (point1[1] < point2[1]) {
                    return -1;
                } else {
                    return 0;
                }
    		}
		});
    	
    	for(int[] point : points) {
    		for(int p : point) {
    			System.out.println(p);
    		}
    	}
    	int n = points.length;
    	int ans = 1;
    	int right = points[0][1];
    	for(int i = 1; i < n ;i++) {
    		if(right <  points[i][0]) {
    			ans++;
    			right = points[i][1];
    		}
    	}
    	return ans;
    }
}

买卖股票的最佳时机2

题目描述:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/

解法1:贪心思想

/**
     * 贪心算法:只要利润为正就买入
     * @param prices
     * @return
     */
    public int maxProfit2(int[] prices) {
    	int n = prices.length;
    	int profit = 0;
    	for(int i = 1; i < prices.length; i++) {
    		int temp = prices[i] - prices[i-1];
    		if(temp > 0) profit += temp; 
    	}
    	return profit;
    }

解法2:动态规划

/**
	 * 动态规划:当天的状态由前一天的状态以及当天的决定有关
	 * @param prices
	 * @return
	 */
    public int maxProfit(int[] prices) {
    	int n =prices.length;
    	int[][] dp = new int[n][2];
    	//dp[i][1]第i天结束持有股票的最大利润,分为第i-1天有股票,和没股票
    	//两种情况
    	//dp[i][0]第i天结束不持有股票的最大利润,分为第i-1天没股票,和
    	///有股票两种情况
    	dp[0][1] = -prices[0];
    	dp[0][0] = 0;
    	for(int i = 1; i < dp.length; i++) {
    		dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0] - prices[i]);
    		dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] + prices[i]);
    	}
    	return dp[n-1][0];
    }

种花问题

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

解法1:贪心思想 在能种的地方尽可能的种花

class Solution {
    public boolean canPlaceFlowers(int[] flowerbed, int n) {
    	int len = flowerbed.length;
    	int place = 0;
    	for(int i = 0; i < len; i++) {
    		//中花的条件:1.当前区域为0 2.左侧为0,或者左侧为边界 3.右侧为0或着右侧为边界
    		if(flowerbed[i] == 0 && ( i == 0|| flowerbed[i-1] == 0 )&& (i == len -1||flowerbed[i+1] == 0)) {
    			place++;
    			flowerbed[i] = 1;
    			if(place >= n) return true;
    		}
    	}
    	return place >= n;
    }
}

判断子序列

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

class Solution {
    public boolean isSubsequence(String s, String t) {
        int index = 0;
        int rightCount = 0;//判断已经匹配的字符个数
    	for(int i = 0; i < s.length(); i++) {
    		while(index < t.length()) {
    			if(s.charAt(i) == t.charAt(index)) {
    				index++;
                    rightCount++;
    				break;
    			}
    			index++;
    		}
    		if(index >= t.length() && rightCount != s.length() ) return false;
    	}
    	return true;
    }
}

子数组最大和

题目描述:https://leetcode-cn.com/problems/maximum-subarray/

解法:没有想到贪心的解法,直接用的滑动窗口来做的

class Solution {
    public int maxSubArray(int[] nums) {
    	int left = 0;//窗口左端
    	int right = 0;//窗口右端
    	int n = nums.length;
    	int maxSum = Integer.MIN_VALUE;//最大和
    	int sum = 0; //当前滑动窗口的和
    	for(;left < n; left++) {
    		right = left;
    		while(right < n) {
    			sum += nums[right];
    			maxSum = Math.max(maxSum, sum);
    			right++;
    		}
    		sum = 0;
    	}
    	return maxSum;
    }
    
}

划分字母空间

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

解法:没啥好说的 积累这种问题吧

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

 

根据引用\[1\]和引用\[2\]的内容,推荐的LeetCode刷题顺序是按照题目类型刷题,优先选择树、链表、二分查找、DFS、BFS、动态规划等常见类型的题目。可以先做2~4道简单题,然后再做中等难度的题目。在选择题目时,可以优先选择题目序号小、点赞多、提交成功率高的题目,这样可以从简单入手,节省时间。同时,LeetCode每道题目都有“模拟面试”功能,可以给自己设定时间限制,如果做不出来可以看答案,然后记住思路后再自己尝试一遍。每种类型的题目做完10+道后,可以总结规律。 根据引用\[3\]的内容,题目可以按照不同的分类进行刷题,比如数组与贪心算法、子数组与贪心算法、子序列与贪心算法、数字与贪心、单调栈法、双指针法等。可以根据自己的兴趣和需求选择相应的题目进行刷题。 综上所述,LeetCode刷题顺序可以按照题目类型或者题目分类进行选择。 #### 引用[.reference_title] - *1* [LeetCode 刷题顺序,按标签分类,科学刷题!](https://blog.csdn.net/fengyuyeguirenenen/article/details/125099023)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [leetcode 刷题指南 & 刷题顺序](https://blog.csdn.net/qijingpei/article/details/125561071)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [leetcode-刷题顺序推荐](https://blog.csdn.net/weixin_38087674/article/details/114107841)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值