1. 包含min函数的栈
(1)题目描述
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
示例:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.min(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.min(); --> 返回 -2.
(2)题目分析
本题可以通过一个辅助栈来实现,用于存储当前栈的最小值。每次入栈的时候,都与辅助栈的栈顶元素进行比较,如果小于等于栈顶元素,则入辅助栈。每次出栈的时候,也与辅助栈的栈顶元素进行比较,如果等于栈顶元素,则出辅助栈。则min()的结果即是辅助栈的栈顶元素的值。
(3)代码
package swordOffer.day5;
import java.util.Stack;
/**
* @author chengzhengda
* @version 1.0
* @date 2020-03-25 18:43
* @desc
*/
public class t21 {
Stack<Integer> stack1;
Stack<Integer> stack2;
public t21() {
stack1 = new Stack();
stack2 = new Stack();
}
public void push(int x) {
if (stack2.empty() || (!stack2.empty() && x <= stack2.peek())) {
stack2.push(x);
}
stack1.push(x);
}
public void pop() {
if (stack1.empty() || stack2.empty()) {
return;
}
int x = stack1.pop();
if (x == stack2.peek()) {
stack2.pop();
}
}
public int top() {
return stack1.peek();
}
public int min() {
return stack2.peek();
}
public static void main(String[] args) {
t21 tt = new t21();
tt.push(3);
tt.push(2);
tt.push(1);
System.out.println(tt.min());
}
}
2. 栈的压入、弹出序列
(1)题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。
示例 1:
输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
输出:true
解释:我们可以按以下顺序执行:
push(1), push(2), push(3), push(4), pop() -> 4,
push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1
(2)题目分析
本题可以通过一个辅助栈来模拟栈的入栈和出栈,每次将pushed数组的元素入栈,然后循环将栈顶元素与poped的元素进行比较,如果相等,则出栈,并将poped的指针右移一位,最后判断辅助栈是否为空,如果为空,则符合要求。
(3)代码
package swordOffer.day5;
import java.util.Stack;
/**
* @author chengzhengda
* @version 1.0
* @date 2020-03-25 19:20
* @desc
*/
public class t23 {
public static boolean validateStackSequences(int[] pushed, int[] popped) {
Stack<Integer> stack = new Stack<>();
int index = 0;
for (int i = 0; i < pushed.length; i++) {
stack.push(pushed[i]);
while (!stack.empty() && index < popped.length && stack.peek() == popped[index]) {
stack.pop();
index++;
}
}
return stack.empty();
}
public static void main(String[] args) {
int push[] = {1, 2, 3, 4, 5};
int pop[] = {4, 5, 3, 2, 1};
System.out.println(validateStackSequences(push, pop));
}
}
3. 数组中出现次数超过一半的数字
(1)题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2
(2)题目分析
本题由于给定的数组总是存在多数元素,因此可以用摩尔投票算法来实现,通过设定一个vote变量,每当出现重复元素时,vote加一,否则,vote减一,当vote等于0时,则改变返回值。
(3)代码
package swordOffer.day5;
/**
* @author chengzhengda
* @version 1.0
* @date 2020-03-25 19:03
* @desc
*/
public class t22 {
public static int majorityElement(int[] nums) {
int x = 0, vote = 0;
for (int num : nums) {
if (vote == 0) {
x = num;
}
vote += num == x ? 1 : -1;
}
return x;
}
public static void main(String[] args) {
int[] nums = {1, 3, 3, 3, 3, 3, 1, 2, 2, 2};
System.out.println(majorityElement(nums));
}
}
4. 最小的k个数
(1)题目描述
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
示例 1:
输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]
(2)题目分析
本题最容易想到的方法就是先将数组排序,然后输出数组前k个数。但是由于本题并没有要求有序输出,因此可以通过对快排算法进行改进来解决。由于快排算法是通过指定一个数,然后将数组中小于该数的值全部移动到该数的左边,数组中大于该数的值全部移动到该数的右边,移动后,通过比较k与指定的数的位置m,如果相等,则直接输出数组的前k个数即可,如果k>m,则递归数组的右数组,如果k<m,则递归数组的左数组。最后输出数组的前k个数即可。
(3)代码
package swordOffer.day5;
/**
* @author chengzhengda
* @version 1.0
* @date 2020-03-25 20:22
* @desc
*/
public class t24 {
public static int[] getLeastNumbers(int[] arr, int k) {
if (k == 0) {
return new int[0];
}
if (arr.length <= k) {
return arr;
}
int res[] = new int[k];
partitionArray(arr, 0, arr.length - 1, k);
for (int i = 0; i < k; i++) {
res[i] = arr[i];
}
return res;
}
public static void partitionArray(int[] arr, int begin, int end, int k) {
int m = quickSort(arr, begin, end);
if (m > k) {
partitionArray(arr, begin, m - 1, k);
} else if (m < k) {
partitionArray(arr, m + 1, end, k);
}
}
public static int quickSort(int[] arr, int begin, int end) {
int i = begin;
int j = end;
int temp = arr[i];
while (i < j) {
while (i < j && arr[j] >= temp) {
j--;
}
arr[i] = arr[j];
while (i < j && arr[i] <= temp) {
i++;
}
arr[j] = arr[i];
}
arr[i] = temp;
return j;
}
public static void main(String[] args) {
int[] arr = {1, 5, 3, 2, 0, 6};
int[] res = getLeastNumbers(arr, 2);
for (int i : res) {
System.out.println(i);
}
}
}
5. 连续子数组的最大和
(1)题目描述
输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
要求时间复杂度为O(n)。
示例1:
输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
(2)题目分析
本题通过设置两个变量,一个sum,一个max,如果sum小于0,则令其等于数组的当前元素,如果不小于0,则sum等于sum加上当前元素,并将sum与max之间的大者赋给max,最后输出max,即为所求。
(3)代码
package swordOffer.day5;
/**
* @author chengzhengda
* @version 1.0
* @date 2020-03-25 21:44
* @desc
*/
public class t25 {
public static int maxSubArray(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int sum = nums[0];
int max = nums[0];
for (int i = 1; i < nums.length; i++) {
if (sum < 0) {
sum = nums[i];
} else {
sum += nums[i];
}
max = Math.max(sum, max);
}
return max;
}
public static void main(String[] args) {
int[] arr = {-2, 1};
System.out.println(maxSubArray(arr));
}
}