LeeCode刷题简记(二)

LeeCode题库 数学

Solution371两整数之和、Solution66加一、Solution89格雷编码、Solution172阶乘后的零、Solution263丑数、Solution264丑数Ⅱ、Solution1492n的第k个因子、Solution1512好数对的数目、Solution1572矩阵对角线元素和、Solution1380矩阵中的幸运数、Solution268丢失的数字、Solution709转成小写字母

Solution371两整数之和

给你两个整数 a 和 b ,不使用 运算符 + 和 - ,计算并返回两整数之和。

class Solution {
    /**
     * 设 a = 6 -> 0110
     *    b = 3 -> 0011
     *  a+b = 9 -> 1001
     *
     * a + b 可以转换为二进制加减,通过位运算 ^ 和 & 进行。
     * 1、通过 & 可知道两数相加后需要进位的部分(a & b -> 0010)然后我们进位 (a & b) << 1 -> 0100,记结果为 i
     * 2、通过 ^ 可知两数相加后无需进位的部分(a ^ b -> 0101),记结果为 j
     *
     * 故 a + b 可转为 i + j,其中 i = 0100, j = 0101,重复前两步操作
     * 1、i & j -> 0100 & 0101 = 0100 , 当其不为 0 时, 进位 (i & j) << 1 -> 1000, 记结果为 i
     * 2、i ^ j -> 0100 ^ 0101 = 0001 , 记结果为 j
     *
     * 重复前两步操作,其中 i = 1000, j = 0001:
     * 1、i & j -> 1000 & 0001 = 0000 , 由于其为 0,跳出循环
     * 2、i ^ j -> 1000 ^ 0001 = 1001 , 结果为 9, 此为最终结果
     *
     * @param a
     * @param b
     * @return
     */
    public static int getSum(int a, int b) {
        // a ^ b 找出需要进位的点
        while ((a & b) != 0) {
            // 进位
            int t = (a & b) << 1;
            // 找出无需进位的点,相加
            b = a ^ b;
            a = t;
        }
        return a ^ b;
    }
}

Solution66加一

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

数组中只能有单数,所以遇十进位,整个数组全是9的话开辟新的数组给第一位赋1.

意思就是数组第一个数必非0,再就是要注意,像[9,9]输出就是[1,0,0]

class Solution {
    public int[] plusOne(int[] digits) {
        for (int i = digits.length - 1; i >= 0; i--){
            if (digits[i] != 9){
                digits[i]++;
                return digits;
            }
            digits[i] = 0;
        }
        int[] temp = new int[digits.length + 1];
        temp[0] = 1;
        return temp;
    }
}

Solution89格雷编码

n 位格雷码序列 是一个由 2n 个整数组成的序列,其中:
每个整数都在范围 [0, 2n - 1] 内(含 0 和 2n - 1)
第一个整数是 0
一个整数在序列中出现 不超过一次
每对 相邻 整数的二进制表示 恰好一位不同 ,且
第一个 和 最后一个 整数的二进制表示 恰好一位不同
给你一个整数 n ,返回任一有效的 n 位格雷码序列 。

class Solution {
    public List<Integer> grayCode(int n) {
        /**
        关键是搞清楚格雷编码的生成过程, G(i) = i ^ (i>>2);
        如 n = 3: 
        G(0) = 000, 
        G(1) = 1 ^ 0 = 001 ^ 000 = 001
        G(2) = 2 ^ 1 = 010 ^ 001 = 011 
        G(3) = 3 ^ 1 = 011 ^ 001 = 010
        G(4) = 4 ^ 2 = 100 ^ 010 = 110
        G(5) = 5 ^ 2 = 101 ^ 010 = 111
        G(6) = 6 ^ 3 = 110 ^ 011 = 101
        G(7) = 7 ^ 3 = 111 ^ 011 = 100
        **/
        List<Integer> ret = new ArrayList<>();
        for(int i = 0; i < 1<<n; ++i)
            ret.add(i ^ i>>1);
        return ret;
    }
}

Solution172阶乘后的零

给定一个整数 n ,返回 n! 结果中尾随零的数量。

提示 n! = n * (n - 1) * (n - 2) * ... * 3 * 2 * 1

 因为只有5才会产生零

class Solution {
    public int trailingZeroes(int n) {
        int count = 0;
        while (n >= 5){//除到没有五
            count += n/5;
            n/=5;
        }
        return count;
    }
}

Solution263丑数

丑数 就是只包含质因数 23 和 5 的正整数。

给你一个整数 n ,请你判断 n 是否为 丑数 。如果是,返回 true ;否则,返回 false 。

 迭代

class Solution {
    public boolean isUgly(int n) {
        if(n == 1) return true;
        if(n <= 0)  return false;
        while(n % 2 == 0 || n % 3 == 0 || n % 5 == 0){
            if(n % 2 == 0){
                n /= 2;
            }else if (n % 3 == 0){
                n /= 3;
            }else if (n % 5 == 0){
                n /= 5;
            }
        }
        if(n == 1 || n == 2 || n == 3 || n == 5) {
            return true;
        }else{
            return false;
        }
    }
}

Solution264丑数Ⅱ

给你一个整数 n ,请你找出并返回第 n 个 丑数 。

丑数 就是只包含质因数 23 和/或 5 的正整数。

 需要动态规划,dp数组存储每三个中最小的丑数

class Solution {
    public int nthUglyNumber(int n) {
        //每个丑数都可以由更小的丑数x2或3或5得到
        int n2 = 0,n3 = 0,n5 = 0;
        int[] dp = new int[n + 1];
        dp[0] = 1;
        for (int i = 1;i < n; i++){
            dp[i] = Math.min(2*dp[n2], Math.min(3*dp[n3], 5*dp[n5]));
            if(dp[i] == 2*dp[n2]){
                n2++;
            }
            if(dp[i] == 3*dp[n3]){
                n3++;
            }
            if(dp[i] == 5*dp[n5]){
                n5++;
            }
        }
        return dp[n - 1];
    }
}

Solution1492n的第k个因子

给你两个正整数 n 和 k 。

如果正整数 i 满足 n % i == 0 ,那么我们就说正整数 i 是整数 n 的因子。

考虑整数 n 的所有因子,将它们 升序排列 。请你返回第 k 个因子。如果 n 的因子数少于 k ,请你返回 -1 。

class Solution {
    public int kthFactor(int n, int k) {
        int i, count = 0;
        for (i = 1; i <= n; i++){
            if(n % i == 0){
                count++;
                if(count == k){
                    return i;
                }
            }
        }
        return -1;
    }
}

Solution1512好数对的数目

给你一个整数数组 nums 。

如果一组数字 (i,j) 满足 nums[i] == nums[j] 且 i < j ,就可以认为这是一组 好数对 。

返回好数对的数目。

若某数字 k 在数组中出现 n 次,那么满足 nums[i] = nums[j] = k 的排列组合应该为 A(n,2),也就是 n(n-1)。但是考虑到 i < j 。那么在所有排列中,只有一半的排列满足要求,即 n(n-1)/2。 

class Solution {
    public int numIdenticalPairs(int[] nums) {
        int[] cnt=new int[101];
        int ans=0;
        //统计次数
        for(int x:nums) cnt[x]++;
        //求和
        for(int n:cnt)  ans+=(n-1)*n/2;
        return ans;
    }
}

Solution1572矩阵对角线元素的和

给你一个正方形矩阵 mat,请你返回矩阵对角线元素的和。

请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。

class Solution {
    public int diagonalSum(int[][] mat) {
        int n = mat.length - 1, sum = 0;
        for (int i = 0; i <= n; i++){
            sum += mat[i][i] + mat[i][n - i];
        }
        return n % 2 == 0 ? sum - mat[n/2][n/2] : sum;
    }
}

Solution1380矩阵中的幸运数

给你一个 m * n 的矩阵,矩阵中的数字 各不相同 。请你按 任意 顺序返回矩阵中的所有幸运数。

幸运数 是指矩阵中满足同时下列两个条件的元素:

在同一行的所有元素中最小
在同一列的所有元素中最大

 自勉,理清思路很重要

class Solution {
    public List<Integer> luckyNumbers (int[][] matrix) {
        List<Integer> res = new ArrayList<>();
        //行数
        int col = matrix.length;
        //列数
        int row = matrix[0].length;
        
        for (int i = 0 ;i< col;i++){
            //记录当前行第一个值作为最小值 进行初始化
            int colMin = matrix[i][0];
            //用于记录当前行最小值的下标
            int idx = 0;
             //对当前行的每一个元素进行遍历找到最小值
            for (int j = 0 ;j< row;j++){
                //滚动变量进行记录
                colMin = Math.min(colMin,matrix[i][j]);
                //将当前行的最小值的坐标赋给idx
                if (colMin == matrix[i][j])idx = j;
            }
            //对于每一列的第一个元素作为最大值进行初始化
            int rowMax = matrix[0][idx];
            //遍历当前第i行所在最小元素的idx列逐一遍历
            for (int j = 0 ;j<col;j++){
                //滚动变量记录当前idx列中的最大值
                rowMax = Math.max(rowMax,matrix[j][idx]);
            }
            //如果这个值既是当前行的最小值 又是idx列的最大值 那么他就是幸运数 添加到结果中即可
            if (colMin == rowMax)res.add(colMin);
        }
        return res ;
    }
}

Solution268丢失的数字

给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。

 跟只出现一次的数字一样,多种思路。

class Solution {
    public int missingNumber(int[] nums) {
        //解法一 排序
        Arrays.sort(nums);
        for(int i = 0; i < nums.length; i++){
            if(nums[i] != i) return i;
        }
        return nums.length;
        
        //解法二 哈希表
        Set<Integer> set = new HashSet<>();
        for(int i = 0; i < nums.length; i++) set.add(nums[i]);   
        for(int i = 0; i <= nums.length; i++)
            if(!set.contains(i)) return i;
        return -1;
        
        //解法三 位运算
        int res = nums.length;
        for(int i = 0; i < nums.length; i++){
            res ^= nums[i] ^ i;
        }
        return res;
        
        //解法四 数学
        int sum = 0;
        for(int i = 0; i < nums.length; i++){
            sum += nums[i];
        }
        return nums.length * (nums.length + 1) / 2 - sum;
    }
}

Solution709转成小写字母

给你一个字符串 s ,将该字符串中的大写字母转换成相同的小写字母,返回新的字符串。

class Solution {
    public String toLowerCase(String str) {
        //大写变小写、小写变大写 : 字符 ^= 32;

        //大写变小写、小写变小写 : 字符 |= 32;

        //小写变大写、大写变大写 : 字符 &= -33
        if(str == null && "".equals(str)){
            return null;
        }

        StringBuilder sb = new StringBuilder();
        for(char c : str.toCharArray()){
            if(c >= 'A' && c <= 'Z'){
                sb.append((char)(c + 32));
            }else{
                sb.append(c);
            }
        }
        return sb.toString();
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值