贪心算法
主要思想:保证每次操作都是局部最优的,并且最后得到的结果是全局最优的
分配饼干
题目描述: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;
}
}