贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。 也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。
这道题目给了我们两组array,一组代表小朋友的胃口值,另一组代表曲奇饼干的大小。
我们要分发曲奇给尽可能多的小朋友,并且曲奇饼干的大小要满足小朋友的胃口。
所以,最好给孩子们分配与他胃口最接近的饼干。
不能把大的曲奇去满足很小胃口的小朋友,除非没有选择。尽可能的去把小曲奇发给小胃口的小朋友。
关键点:把两个array 重新排列,从小到大。
对两个数组进行排序并使用两个指针。O(nlogn)
// 10ms
class Solution {
public int findContentChildren(int[] g, int[] s) {
Arrays.sort(g);
Arrays.sort(s);
int pointG = 0;
int pointS = 0;
while (pointG < g.length && pointS < s.length) {
if (g[pointG] <= s[pointS]) {
pointG++;
pointS++;
}
else {
pointS++;
}
}
return pointG;
}
}
常规循环两个数组遍历,无指针,效率慢
class Solution {
public int findContentChildren(int[] g, int[] s) {
int count=0;
Arrays.sort(g);
Arrays.sort(s);
int j=0;
for(int i=0; i<g.length; i++){
while(j<s.length && s[j]<g[i]) j++;
if(j==s.length) break;
count++;
j++;
}
return count;
}
}
题目链接
给定一个非负整数数组,数组中的每个元素表示该位置的最大跳跃长度。
从数组的第一个索引(下标为0)开始,确定是否能够跳到最后一个索引处。
Example 1:
Input: [2,3,1,1,4]
Output: true
Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.
Example 2:
Input: [3,2,1,0,4]
Output: false
Explanation: You will always arrive at index 3 no matter what. Its maximum jump length is 0, which makes it impossible to reach the last index.
采用贪心的思路,采用farest变量表示到目前为止能跳到的最远距离,即为全局最优解。当遍历到 i 的时候,局部最优解为 A[i]+i,表示从当前一步出发能跳到的最远距离。
因此,此时的全局最优解即为 farest 和 A[i]+i 的最大值:farest = Math.max(farest, A[i] + i)。
关键点:“局部最优和全局最优解法”。全局最优为 globalMax=Math.max(globalMax, localMax)
public boolean canJump(int[] A) {
int n = A.length;
int farest = 0;
for(int i = 0; i < n; i++){
if(farest < i) return false;
farest = Math.max(i + A[i], farest);
}
return true;
}
题目链接
给定一个非负整数数组,数组中的每个元素表示该位置的最大跳跃长度。
从数组的第一个索引(下标为0)开始,需要我们以最小跳跃次数到达最后一个索引。
Example:
Input: [2,3,1,1,4] Output: 2
Explanation: 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.
Note: You can assume that you can always reach the last index.
这道题需要求的是最少的步数。
因此需要添加step变量记录最少步数。至于什么时候step需要加1?答案是当前的 i 超过了前一step的最远位置。所以引入last变量记录上一步step能到达的最远位置。
当遍历到 i 的时候,如果 i == last(即上一step能到达的最远位置),说明步数需要加1(step++),此时仍需要更新last为当前最远位置farest。
关键点:记录最少步数step、判断何时step++
public int jump(int[] A) {
int n = A.length;
int step = 0, last = 0, farest = 0;
for(int i = 0; i < n-1; i++) {
farest = Math.max(farest, i+A[i]);
if(farest >= n-1) return step+1; //skip scanning when find a way with minimum jumps
if(i == last) {
step++;
last = farest;
}
}
return step ;
}
题目链接
假设您有一个数组, i t h i^{th} ith元素是第 i 天股票的价格。
设计算法以找到最大利润。 您可以根据需要完成尽可能多的交易(即,多次进行买入卖出)。
注意:您不得同时进行多笔交易(即,您必须在再次购买之前卖出股票)。
Example 1:
Input: [7,1,5,3,6,4]
Output: 7
Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4. Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3.
Example 2:
Input: [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4. Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are engaging multiple transactions at the same time. You must sell before buying again.
Example 3:
Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
贪心算法,在每一小段上升序列中最大差值累加得到结果。就是说在股票价格处于上升期的时候,在最低点买入,在最高点卖出。
class Solution {
public int maxProfit(int[] prices) {
int pro = 0;
for (int i = 1; i < prices.length; i++){
if (prices[i]> prices[i-1])
pro += prices[i] - prices[i-1];
}
return pro;
}
}
题目链接
沿着环形路线有N个加油站,在加油站 i 的汽油数是 gas[i]。
你有一辆带有无限油箱的汽车,从加油站i 到下一加油站 (i+1) 需要消耗cost[i]汽油。 您使用空罐从其中任一个加油站启程。如果您可以顺时针方向绕环形一次,则返回起始加油站的索引,否则返回-1。
注意: 如果存在解决方案,则保证是唯一的。
Example 1:
Input: gas = [1,2,3,4,5]; cost = [3,4,5,1,2]
Output: 3
Explanation: Start at station 3 (index 3) and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 4. Your tank = 4 - 1 + 5 = 8
Travel to station 0. Your tank = 8 - 2 + 1 = 7
Travel to station 1. Your tank = 7 - 3 + 2 = 6
Travel to station 2. Your tank = 6 - 4 + 3 = 5
Travel to station 3. The cost is 5. Your gas is just enough to travel back to station 3. Therefore, return 3 as the starting index.
Example 2:
Input: gas = [2,3,4] cost = [3,4,3]
Output: -1
Explanation: You can’t start at station 0 or 1, as there is not enough gas to travel to the next station. Let’s start at station 2 and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 0. Your tank = 4 - 3 + 2 = 3
Travel to station 1. Your tank = 3 - 3 + 3 = 3
You cannot travel back to station 2, as it requires 4 unit of gas but you only have 3. Therefore, you can’t travel around the circuit once no matter where you start.
首先先要明白:如果一个数组的总和非负,那么一定可以找到一个起始位置,从他开始绕数组一圈,累加和一直都是非负的。
如果从 i 出发,那么 gas[i]- cost[i] = dif[i] 一定是大于0的。
如果 dif[i] + dif[i+1] +……+ dif[k-1]>=0,而 dif[i] + dif[i+1] +……+ dif[k-1] + dif[k]<0,此时需要重新设置开始点,那么需要从i+1开始吗?从i+1开始肯定不可能到达k点(dif[i]肯定大于0,所以少加了一个正数)。
那么需要设置开始点为 k+1
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int startpos = 0; // 记录访问的起始点
int totaldif = 0; // 从0位置开始,加的气和消耗的气的总差值
int startdif = 0; // 从start位置开始,加的气和消耗的气的总差值
for (int i = 0; i < gas.length; i++){
int dif = gas[i] - cost[i];
totaldif += dif;
startdif += dif;
if (startdif < 0){ // 走到i站是负数,说明走不到i站;也不能选取起始站到i站中的任何一站
startdif = 0;
startpos = i + 1; // 直接选择下一站作为起始点
}
}
return totaldif >= 0 ? startpos : -1;
}
}
题目链接
在柠檬水摊上,每个柠檬水的价格为5美元。
客户站在队列中向您购买,并一次订购一个(按照账单指定的顺序)。
每位顾客只需购买一瓶柠檬水,并以5美元,10美元或20美元的钞票付款。 您必须找给每个客户正确的零钱。
请注意,您最初手头没有任何零钱。当且仅当您能为每位客户提供正确的零钱时,才返回true。
Example 1:
Input: [5,5,5,10,20]
Output: true
Explanation: From the first 3 customers, we collect three $5 bills in order.
From the fourth customer, we collect a $10 bill and give back a $5.
From the fifth customer, we give a $10 bill and a $5 bill.
Since all customers got correct change, we output true.
Example 2:
Input: [5,5,10,10,20]
Output: false
Explanation: From the first two customers in order, we collect two $5 bills.
For the next two customers in order, we collect a $10 bill and give back a $5 bill.
For the last customer, we can’t give change of $15 back because we only have two $10 bills.
Since not every customer received correct change, the answer is false.
class Solution {
public boolean lemonadeChange(int[] bills) {
int five = 0, ten = 0;
for (int i : bills) {
if (i == 5) five++;
else if (i == 10) {five--; ten++;}
else if (ten > 0) {ten--; five--;}
else five -= 3;
if (five < 0) return false;
}
return true;
}
}