剑指offer(二)

栈的压入、弹出序列

包含min函数的栈

用两个栈实现队列

数值的整数次方

二进制中1的个数

旋转数组中的最小数

矩形覆盖

跳台阶

二维数组中的查找

替换空格

斐波那契数列

斐波那契数列

 输入一个整数n,输出斐波那契数列的第n项。n是从0开始。0,1,1,2,3,5...

// 不能通过测试...超时
public int Fibonacci(int n) {
    if(n==0 || n==1){
        return n;
    }
    return Fibonacci(n-1) + Fibonacci(n-2);
}

 
public int Fibonacci(int n){
    if(n==0 || n==1){
        return n;
    }
     
    int preNum=1;
    int prePreNum=0;
    int result=0;
     
    for(int i=2; i<=n; i++){
        result = preNum + prePreNum;
        prePreNum = preNum;
        preNum = result;
    }
    return result;
}

用两个栈实现队列

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型.

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    
    public void push(int node) {
        stack1.push(node);
    }
    
    public int pop() {
        if(stack2.empty()){
            while(!stack1.empty()){
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }
}

替换空格

将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

// 开辟新空间
public String replaceSpace2(StringBuffer str) {
    int len = str.length();
    StringBuffer result = new StringBuffer();
    for(int i=0; i<len; i++){
        if(str.charAt(i) == ' '){
            result.append("%20");
        }else{
            result.append(str.charAt(i));
        }
    }
    return result.toString();
}

//在原来的字符串上做替换
public String replaceSpace(StringBuffer str){
    int spaceNum = 0;
    for(int i=0; i<str.length(); i++){
        if(str.charAt(i)==' ')
            spaceNum++;
    }
    
    int oldIndex = str.length()-1; //替换前的下标

    int newLength = str.length() + spaceNum*2;
    str.setLength(newLength); // 替换后的str长度
    int newIndex = newLength-1; // 替换后的下标
    
    for(; oldIndex>=0 && oldIndex<newLength; --oldIndex){
        if(str.charAt(oldIndex)==' '){
            str.setCharAt(newIndex--, '0');
            str.setCharAt(newIndex--, '2');
            str.setCharAt(newIndex--, '%');
        }else{
            str.setCharAt(newIndex--, str.charAt(oldIndex));
        }
    }
    return str.toString();
}

// replace函数
public String replaceSpace3(StringBuffer str) {
    return str.toString().replaceAll("\s", "%20");
}

二维数组中的查找 

在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

// 从数组左下角开始查找
public boolean find(int [][] array,int target) {
    int m = array.length-1;
    int n = array[0].length-1;
    
    int i=0;
    while(m>=0 && i<=n){
        if(target < array[m][i]){
            m--;
        }else if(target > array[m][i]){
            i++;
        }else{
            return true;
        }
    }
    return false;
}

// 从数组右上角开始查找
public boolean find(int[][] array, int target){
    int n = array[0].length-1;
    int i = 0;
    while(n>=0 && i<array.length){
        if(target > array[i][n]){
            i++;
        }else if(target < array[i][n]){
            n--;
        }else{
            return true;
        }
    }
    return false;
}

// 遍历每一行,每一行中二分查找
public boolean find(int[][] array, int target){
    for(int i=0; i<array.length; i++){
        int low=0; 
        int high=array[i].length-1;
        
        while(low <= high){
            int mid = (low + high)/2;
            if(target > array[i][mid]){
                low = mid+1;
            }else if(target < array[i][mid]){
                high = mid-1;
            }else{
                return true;
            }
        }   
    }
    return false;
}

跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法

// 一、递归... 超时
public int jumpFloor(int n){
    if(n<=1){
        return 1;
    }
    if(n==2){
        return 2;
    }
    
    return jumpFloor(n-2) + jumpFloor(n-1);
    
}
// 动态规划
public int jumpFloor(int n){
    if(n<=1){
        return 1;
    }
    
    int last = 1;
    int lastLast = 1;
    int now = 0;
    
    for(int i=2; i<=n; i++){
        now = last + lastLast;
        lastLast = last;
        last = now;
    }
    return now;
}

变态跳台阶:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

// 一、递归
pubic int jumpFloorII(int n){
    if(n==1){
        return 1;
    }
    return 2*jumpFloor(n-1);
}
// 二、
pubic int jumpFloorII(int n){
    int a = 1;
    return a<<(n-1);
}

矩形覆盖

用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法

//一、递归
public int RectCover(int n) {
    if(n<=0){
        return 0;
    }
    if(n==1){
        return 1;
    }
    if(n==2){
        return 2;
    }
    return RectCover(n-1)+RectCover(n-2); // 递归
}

//二、减少耗时
public int RectCover(int n) {
    if(n<=0){
        return 0;
    }
    if(n==1){
        return 1;
    }
    if(n==2){
        return 2;
    }
    
    int p = 2; 
    int pp = 1;
    int res = 0;
    for(int i=3; i<=n; i++){
        res = p+pp;
        pp = p;
        p = res;
    }
    return res;
}

旋转数组中的最小数

public int minNumberInRotateArray(int [] array) {
    if(array == null || array.length == 0){
        return 0;
    }
    
    if(array[0]<array[array.length-1]){
        return array[0];
    }
    
    for(int i=0; i<array.length-1; i++){
        if(array[i]>array[i+1]){
            return array[i+1];
        }
    }
    
    return 0;
}

二进制中1的个数

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

public int  numberOf1(int n) {
    int count = 0;
    int one = 1;
    while(one!=0){
        if((one & n)!=0){
            count++;
        }
        one = one << 1;
    }
    return count;
}

数值的整数次方

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

public double power(double base, int exponent) {
    int n;
    if(exponent==0){
        return 1;
    }
    if(exponent<0){
        if(base==0){
            throw new RuntimeException("分母不能为0");
        }
        n = -exponent;
    }else{
        n = exponent;
    }
    
    double result=1;
    for(int i=0; i<n; i++){
        result = result*base;
    }
    return exponent>0?result:(1/result);
}

包含min函数的栈

定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。

public class Solution {
    Stack<Integer> data = new Stack<>();
    Stack<Integer> min = new Stack<>();
    
    Integer tmp = null;
    public void push(int node) {
        if(tmp!=null){
            if(node<=tmp){
                tmp = node;
                min.push(node);
            }
            data.push(node);
        }else{
            min.push(node);
            tmp = node;
            data.push(node);
        }
        
    }
    
    public void pop() {
        int num = data.pop();
        int num2 = min.pop();
        if(num!=num2){
            min.push(num2);
        }
    }
    
    public int top() {
        int num = data.pop();
        data.push(num);
        return num;
    }
    
    public int min() {
        int num = min.pop();
        min.push(num);
        return num;
    }
}

栈的压入、弹出序列

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。

假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。

public boolean isPopOrder(int [] pushA,int [] popA) {
    if(pushA==null && popA==null){
        return false;
    }
    
    Stack<Integer> stack = new Stack<>();
    for(int i=0, j=0; i<pushA.length; i++){
        stack.push(pushA[i]);
        while(!stack.isEmpty() && popA[j]==stack.peek()){
            stack.pop();
            j++;
        }
    }
    return stack.isEmpty();
}
原文地址:https://www.cnblogs.com/hesier/p/5718109.html