《剑指offer第二版》五

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));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值