232. 用栈实现队列
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列的支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
说明:
你只能使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
思路
用栈实现队列,需要两个栈。
因为队列是先进先出,而栈是先进后出,所以要改变顺序,需要将其中一个栈来做进队操作,而另外一个栈做出队操作。数据顺序在两个栈中间进行改变
class MyQueue {
Stack<Integer> s1;
Stack<Integer> s2;
/** Initialize your data structure here. */
public MyQueue() {
s1 = new Stack<>();
s2 = new Stack<>();
}
/** Push element x to the back of queue. */
public void push(int x) {进队--在s1入栈
s1.push(x);
}
/** Removes the element from in front of queue and returns that element. */
public int pop() {//出栈
if(s2.isEmpty()) { --s2为空
while(!s1.isEmpty()) {//s1不为空--将s1的元素全部压入s2.弹出s2栈顶
s2.push(s1.pop());
}
}
if(!s2.isEmpty()){//s2不为空
return s2.pop();
}
return -1;
}
/** Get the front element. */
public int peek() {
if(!s2.isEmpty()){
return s2.peek();
}
if(!s1.isEmpty()) {
while(!s1.isEmpty()) {
s2.push(s1.pop());
}
}
return s2.isEmpty() ? -1 : s2.peek();
}
/** Returns whether the queue is empty. */
public boolean empty() {
if(s1.isEmpty() && s2.isEmpty()) {
return true;
}
return false;
}
}
122. 买卖股票的最佳时机 II
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
思路
1.这个题模拟股票交易最理想的状态–获得最大利润,那就是要在低点买入,高点卖出(画图很直观),最佳收益也就是差值为正的时候
2.所以求出每只股票与前一天的差值,为正即可
3.第一天的差值设为0.
4.综上,可以初探贪心策略:我们的目的是要求得整个买卖周期的最大收益。那么将整个买卖周期进行拆分,转化成为局部最大收益。每求解出一个局部最大收益,那么相对应的整体收益就会发生改变(贪心策略的特点)。而相对应的,动态规划求解的时候,局部解对整体解的正确结果没有影响,但是是一步步构成整体解的~
完整代码
public int maxProfit(int[] prices) {
int n = prices.length;
if(n == 0) {
return 0;
}
int[] abs = new int[n];
abs[0] = 0;
for(int i = 1; i < n; i++) {
abs[i] = prices[i] - prices[i - 1];
}
int res = 0;
for(int i = 0; i < n; i++) {
if(abs[i] > 0) {
res += abs[i];
}
}
return res;
}
55. 跳跃游戏
给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个下标。
思路
用贪心算法的思想。
1.维护一个最远能够到达的坐标数组
2.用一个max变量储存已经遍历的元素所能够到达的最远位置。
3.如果当前坐标大于max,说明之前的坐标并不能跳过来。
4.如果当前坐标小于max,更新max,同时判断是否能够跳到终点
优化
这里的数组可以删掉,只要实时维护max变量就好了(但是作为贪心入门,还是建议不要跳过数组的维护)。
完整代码
int n = nums.length;
int[] canJumps = new int[n];
for(int i = 0; i < n - 1; i++) {
canJumps[i] = nums[i] + i;
}
int max = 0;
for(int i = 0; i < n - 1; i++) {
if(i <= max) {
max = Math.max(max, canJumps[i]);
if(canJumps[i] >= n - 1) {
return true;
}
}
}
return false;