leetcode_jz

1.力扣_jz66_构建乘积数组

/**
 * 给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中B[i] 的值是数组 A 中除了下标 i 以外的元素的积
 * 即B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]。不能使用除法。
 **/
public class Num66_构建乘积数组 {
    /*方法1:左右乘积列表*/

    /**
     * 当前元素的值=除当前元素以外的元素的乘积=当前元素左边元素的总乘积*当前元素右边元素的总乘积
     * 构建两个新数组left[]+right[],left[i]存储索引元素左边元素的总乘积,right[i]存储当前元素左边元素的总乘积
     * 对于left数组,left[0]=1,因为第一个元素左边没有元素。其他元素:left[i]=left[i-1]*a[i-1]
     * 对于right数组,right[length-1]=1,因为最后一个元素右边没有元素。其他元素:right[i]=right[i+1]*a[i+1]
     * B[i]存储除当前下标以外的元素的乘积=i下标左侧元素之积*i下标右侧元素之积=left[i]*right[i]
     * @param a
     * @return
     */
    public int[] constructArr(int[] a) {
        int len=a.length;
        int left[]=new int[len];
        int right[]=new int[len];
        int B[]=new int[len];
        if(a==null||a.length==0){
            return B;
        }
        //left[i]
        left[0]=1;
        for (int i = 1; i < len; i++) {
            left[i]=left[i-1]*a[i-1];
        }
        //right[i]
        right[len-1]=1;
        for (int i = len-2; i >= 0; i--) {
            right[i]=right[i+1]*a[i+1];
        }
        //B[i]
        for (int i = 0; i < len; i++) {
            B[i]=left[i]*right[i];
        }
        return B;
    }
    /*方法2:让B[i]直接表示i左侧元素乘积,遍历完左侧后定义一个数动态表示右侧乘积r。上一个方法空间复杂度O(n),这个O(1)*/
    /**
     * 由于输出数组不算在空间复杂度内,那么我们可以将 L 或 R 数组用输出数组来计算。
     * 先把输出数组当作 L 数组来计算,然后再动态构造 R 数组得到结果。让我们来看看基于这个思想的算法。
     * 算法
     * 初始化 answer 数组,对于给定索引 i,answer[i] 代表的是 i 左侧所有数字的乘积。
     * 构造方式与之前相同,只是我们试图节省空间,先把 answer 作为方法一的 L 数组。
     * 这种方法的唯一变化就是我们没有构造 R 数组。而是用一个遍历来跟踪右边元素的乘积。并更新数组 answer[i]=answer[i]*Ranswer[i]=answer[i]∗R。然后 RR 更新为 R=R*a[i]R=R∗a[i],其中变量 RR 表示的就是索引右侧数字的乘积。
     */
    public int[] constructArr2(int[] a) {
        //要创建的B数组直接先表示为求左侧元素乘积
        int[] B=new int[a.length];
        if (a==null||a.length==0){
            return B;
        }
        // B[i] 表示索引 i 左侧所有元素的乘积
        // 因为索引为 '0' 的元素左侧没有元素, 所以 B[0] = 1
        B[0]=1;
        for (int i = 1; i < B.length; i++) {
            B[i]=B[i-1]*a[i-1];
        }


        // r 为右侧所有元素的乘积
        // 刚开始右边没有元素,所以 r = 1
        int r=1;
        for (int i = B.length-1; i >= 0; i--) {
            B[i]=B[i]*r;//i的左侧元素的积B[i]*右侧元素的乘积r
            // r 需要包含右边所有的乘积,所以计算下一个结果时需要将当前值a[i]乘到 r 上
            r*=a[i];
        }
        return B;
    }
}

2.力扣_数值的整数次方

        实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,x^n)。不得使用库函数,同时不需要考虑大数问题

//方法1:递归
    public double myPow(double x, int n) {
        long N=n;
        //x^n,n>=0时正常计算,n<=0时先N=-N,再在最后结果上求倒数即得到结果:eg:2^2=4;2^-2=1/(-(-2))^2=1/4
        return N>=0?quickMul(x,N):1.0/quickMul(x,-N);
    }

    private double quickMul(double x, long N) {
        if(N==0){
            return 1;
        }
        double res=quickMul(x,N/2);
        return N%2==0?res*res:res*res*x;
    }

//方法2:迭代
    public double myPow1(double x, int n) {
        long N=n;
        //x^n,n>=0时正常计算,n<=0时先N=-N,再在最后结果上求倒数即得到结果:eg:2^2=4;2^-2=1/(-(-2))^2=1/4
        return N>=0?quickMul1(x,N):1.0/quickMul1(x,-N);
    }

    private double quickMul1(double x, long N) {
        double res=1.0;
        // 贡献的初始值为 x
        double x_con=x;
        // 在对 N 进行二进制拆分的同时计算答案
        while (N>0){
            if(N%2==1){
                // 如果 N 二进制表示的最低位为 1,那么需要计入贡献
                res*=x_con;
            }
            // 将贡献不断地平方
            x_con*=x_con;
            // 舍弃 N 二进制表示的最低位,这样我们每次只要判断最低位即可
            N/=2;
        }
        return res;
    }

3.力扣_打印1到最大的n位数

public class Num17_打印从1到最大的n位数 {
    public int[] printNumbers(int n) {
        int end=(int) Math.pow(10,n)-1;
        int[] res=new int[end];
        for (int i = 0; i < end; i++) {
            res[i]=i+1;
        }
        return res;
    }
}

大数打印解法:力扣

4.力扣_表示数值的字符串

class Solution {
    public boolean isNumber(String s) {
         if(s == null || s.length() == 0) return false; // s为空对象或 s长度为0(空字符串)时, 不能表示数值
        boolean isNum = false, isDot = false, ise_or_E = false; // 标记是否遇到数位、小数点、‘e’或'E'
        char[] str = s.trim().toCharArray();  // 删除字符串头尾的空格,转为字符数组,方便遍历判断每个字符
        for(int i=0; i<str.length; i++) {
            if(str[i] >= '0' && str[i] <= '9') isNum = true; // 判断当前字符是否为 0~9 的数位
            else if(str[i] == '.') { // 遇到小数点
                if(isDot || ise_or_E) return false; // 小数点之前可以没有整数,但是不能重复出现小数点、或出现‘e’、'E'
                isDot = true; // 标记已经遇到小数点
            }
            else if(str[i] == 'e' || str[i] == 'E') { // 遇到‘e’或'E'
                if(!isNum || ise_or_E) return false; // ‘e’或'E'前面必须有整数,且前面不能重复出现‘e’或'E'
                ise_or_E = true; // 标记已经遇到‘e’或'E'
                isNum = false; // 重置isNum,因为‘e’或'E'之后也必须接上整数,防止出现 123e或者123e+的非法情况
            }
            else if(str[i] == '-' ||str[i] == '+') { 
                if(i!=0 && str[i-1] != 'e' && str[i-1] != 'E') return false; // 正负号只可能出现在第一个位置,或者出现在‘e’或'E'的后面一个位置
            }
            else return false; // 其它情况均为不合法字符
        }
        return isNum;
    }
}

5.力扣_顺时针打印矩阵

public static int[] spiralOrder(int[][] matrix) {
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return new int[0];
        }
        int rows = matrix.length, columns = matrix[0].length;
        int[] order = new int[rows * columns];
        int index = 0;
        int left = 0, right = columns - 1, top = 0, bottom = rows - 1;
        while (left <= right && top <= bottom) {
            for (int column = left; column <= right; column++) {
                order[index++] = matrix[top][column];
            }
            for (int row = top + 1; row <= bottom; row++) {
                order[index++] = matrix[row][right];
            }
            if (left < right && top < bottom) {
                for (int column = right - 1; column > left; column--) {
                    order[index++] = matrix[bottom][column];
                }
                for (int row = bottom; row > top; row--) {
                    order[index++] = matrix[row][left];
                }
            }
            left++;
            right--;
            top++;
            bottom--;
        }
        return order;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值