Leetcode 第66,100,118,119,125,171,191,202,219,228题(Java解法)

这篇博客详细介绍了LeetCode中10道Java解法,包括加一、相同的树、杨辉三角及其变种、验证回文串、Excel表列序号、位1的个数、快乐数、存在重复元素II、汇总区间等题目,涉及二叉树、字符串、数组和位运算等多个算法知识点。
摘要由CSDN通过智能技术生成

第66题 加一

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。

示例 1:

输入输出
digits = [1,2,3][1,2,4]

输入数组表示数字 123。

示例 2:

输入输出
digits = [4,3,2,1][4,3,2,2]

解释:输入数组表示数字 4321。

示例 3:

输入输出
digits = [0][1]

解题思路

直接使用数组解题,首先从数组末尾开始遍历,如果末尾数字加1之后对10取余不为0,则说明没有进位,可以直接返回数组;如果为0,说明有进位,则继续向前遍历,然后加1,判断是否有进位,如果遍历结束后仍有进位,则在最后的数组首部加入1,实现进位。

代码

// 加一:数学
class Solution {
    public int[] plusOne(int[] digits) {
        for (int i = digits.length - 1; i >= 0; i--) {//从数组末尾开始遍历
            digits[i]++;
            digits[i] = digits[i] % 10;//让数字自增,然后判断是否有进位
            if (digits[i] != 0) return digits;//没有进位则直接输出数组,有进位则继续执行循环条件
        }
        digits = new int[digits.length + 1];//如果遍历完了数字,仍存在进位,则在数组首部加1
        digits[0] = 1;
        return digits;
    }
}

时间复杂度为O(n),n为数组长度
空间复杂度为O(1)

第100题 相同的树/font>

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:

输入输出
p = [1,2,3], q = [1,2,3]True

示例 2:

输入输出
p = [1,2]false

示例 3:

输入输出
p = [1,2,1], q = [1,1,2]false

解题思路

本题使用深度搜索,比较两棵树各对应节点的值。

代码

// 相同的树:dfs
class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if (p == null && q == null) {
            return true;
        } else if (p == null || q == null) {
            return false;
        } else if (p.val != q.val) {
            return false;
        } else {
            return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
        }
    }
}

时间复杂度为O(min(m,n)),m,n为两棵树的节点数
空间复杂度为O(min(m,n))

第118题 杨辉三角

给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。
在杨辉三角中,每个数是它左上方和右上方的数的和。

示例 1:

输入输出
5[[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]

解题思路

杨辉三角有一个规律,就是每一行的列数与当前的行数相同,还有规律就是每一行的第一列和最后一列都为1,其余列的值等于同一列上的上一行的值加上前一个左上角的数字。

代码

// 杨辉三角:数组
class Solution {
    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> ret = new ArrayList<List<Integer>>();//建立一个数组
        for (int i = 0; i < numRows; ++i) {//建立每一行
            List<Integer> row = new ArrayList<Integer>();//建立一个一维数组
            for (int j = 0; j <= i; ++j) {//对应行数有相应的列数,j为列数
                if (j == 0 || j == i) {
                    row.add(1);//每一行第一个数字和最后一个数字都是1
                } else {
                    row.add(ret.get(i - 1).get(j - 1) + ret.get(i - 1).get(j));//每一行除了第一列和最后一列数字以外,其余列的值等于它同一列的前一行的值加上上一列上一行的值
                }
            }
            ret.add(row);
        }
        return ret;
    }
}

时间复杂度为O( n u m R o w s 2 numRows^2 numRows2),给定数字的平方。
空间复杂度为O(1)

第119题 杨辉三角 II

给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行。
在杨辉三角中,每个数是它左上方和右上方的数的和。

示例 1:

输入输出
3[1,3,3,1]

解题思路

利用数学知识,当前所求的数=前一个数乘上给定数字减去所求数的列数加1,然后再除去所求数的列数,就能得到结果

代码

// 杨辉三角 II:数学
class Solution {
    public List<Integer> getRow(int rowIndex) {
        List<Integer> row = new ArrayList<Integer>();
        row.add(1);//第一列都为1
        for (int i = 1; i <= rowIndex; ++i) {
            row.add((int) ((long) row.get(i - 1) * (rowIndex - i + 1) / i));//拿3举例,第2列为第一列的值1乘上3减索引1加1的值等于3,再除以索引1,得到最后值为3,第3列为第二列的值3乘3减索引2加1的值为6,再除以索引2,得到最后的值为3
        }
        return row;
    }
}

时间复杂度为O(rowIndex),rowIndex为给定的行数
空间复杂度为O(1)

第125题 验证回文串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。

示例 1:

输入输出
“A man, a plan, a canal: Panama”true

示例 2:

输入输出
“race a car”false

解题思路

建立双指针,一个从头遍历,一个从尾遍历,遇到非数字或字符的就直接移动指针,如果左右指针所指的字符相等,则同时向右向左移动指针,如果左指针大于右指针,则该字符串是回文串,如果指针所指字符不相等,则说明不是回文串

代码

// 验证回文串:双指针
class Solution {
    public boolean isPalindrome(String s) {
        int n = s.length();
        int left = 0, right = n - 1;
        while (left < right) {
            while (left < right && !Character.isLetterOrDigit(s.charAt(left))) {
                ++left;
            }
            while (left < right && !Character.isLetterOrDigit(s.charAt(right))) {
                --right;
            }//判断左右指针所指是否为数字或字符,如果不是则移动指针
            if (left < right) {
                if (Character.toLowerCase(s.charAt(left)) !=Character.toLowerCase(s.charAt(right))) {
                    return false;
                }//如果在左右指针索引不相等的情况下,所指字符不一致,则说明不是回文串
                ++left;
                --right;
            }//如果相等则同时移动指针
        }
        return true;
    }
}

时间复杂度为O(s),s为字符串的长度
空间复杂度为O(1)

第171题 Excel表列序号

给定一个Excel表格中的列名称,返回其相应的列序号。
例如,

A -> 1
B -> 2
C -> 3
...
Z -> 26
AA -> 27
AB -> 28 
...

示例 1:

输入输出
“A”1

示例 2:

输入输出
“AB”28

示例 3:

输入输出
“ZY”701

解题思路

遍历字符串,取每个字母,每取一次字符,将其转换为数字后加上原结果乘26的数值,直到遍历完字符串

代码

// Excel表列序号:字符串
class Solution {
    public int titleToNumber(String s) {
        int ans = 0;
        for(int i=0;i<s.length();i++) {
            int num = s.charAt(i) - 'A' + 1;
            ans = ans * 26 + num;
        }
        return ans;
    }
}

时间复杂度为O(s),s为字符串长度
空间复杂度为O(1)

第191题 位1的个数

编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。

示例 1:

输入输出
000000000000000000000000000010113

输入的二进制串 00000000000000000000000000001011 中,共有三位为 ‘1’。

示例 2:

输入输出
000000000000000000000000100000001

输入的二进制串 00000000000000000000000010000000 中,共有一位为 ‘1’。

示例 3:

输入输出
1111111111111111111111111111110131

输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 ‘1’。

解题思路

运用位运算求解,让数字与比它小一的数字进行&操作,能够将数字右边第1个1变成0,然后用ret记录一次,再循环进行&操作,直到数字变成0

代码

// 位1的个数:位运算
public class Solution {
    public int hammingWeight(int n) {
        int ret = 0;
        while (n != 0) {
            n &= n - 1;//把二进制低位1变成0,如6=110,6&6-1即110&101=100,把第二位的1变成了0
            ret++;//记录一个1
        }
        return ret;
    }
}

时间复杂度为O(log n),n为二进制中1的的个数
空间复杂度为O(1)

第202题 快乐数

编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果 可以变为 1,那么这个数就是快乐数。
如果 n 是快乐数就返回 true ;不是,则返回 false 。

示例 1:

输入输出
19true

解释:
1² + 9² = 82
8² + 2² = 68
6² + 8² = 100
1² + 0² + 0² = 1

示例 2:

输入输出
n = 2false

解题思路

本题利用双指针解题,如果快慢指针相等,则说明进入了循环,代表数字永远在循环中,不是快乐数,如果慢指针执行getNext操作后,得到了1,则说明原数字是快乐数。

代码

// 快乐数:双指针
class Solution {

     public int getNext(int n) {
        int totalSum = 0;
        while (n > 0) {
            int d = n % 10;
            n = n / 10;
            totalSum += d * d;
        }//得到新数字
        return totalSum;//返回新数字
    }

    public boolean isHappy(int n) {
        int slowRunner = n;
        int fastRunner = getNext(n);
        while (fastRunner != 1 && slowRunner != fastRunner) {//判断是否已经为快乐数或者快慢指针已经相等
            slowRunner = getNext(slowRunner);//慢指针进行一次getNext操作
            fastRunner = getNext(getNext(fastRunner));//快指针执行两次getNext操作,如果快慢指针相等,则说明是一个环,代表数字永远不会等于单个1
        }
        return fastRunner == 1;//当数字等于1时,则代表原数字是快乐数
    }
}

时间复杂度为O(log n),n为慢指针循环执行次数
空间复杂度为O(1)

第219题 存在重复元素 II

给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。

示例 1:

输入输出
nums = [1,2,3,1], k = 3true

示例 2:

输入输出
nums = [1,0,1,1], k = 1true

示例 3:

输入输出
nums = [1,2,3,1,2,3], k = 2false

解题思路

遍历数组,如果遇到了同样的数,则返回true,否则将数字加入哈希表中,如果哈希表的长度超过了给定值,则将最开始的元素删除,因为即使再出现所删除的数,它们的距离也已经超过了给定值,不符合要求。

代码

// 存在重复元素 II:哈希表
public boolean containsNearbyDuplicate(int[] nums, int k) {
    Set<Integer> set = new HashSet<>();
    for (int i = 0; i < nums.length; ++i) {
        if (set.contains(nums[i])) return true;//判断数组中是否存在同样的数
        set.add(nums[i]);//如果没有则将数存储
        if (set.size() > k) {//如果哈希表的大小大于给定值,则移除开始的元素
            set.remove(nums[i - k]);
        }
    }
    return false;
}

时间复杂度为O(n),n为数组长度
空间复杂度为O(min(n,k)),哈希表存储的元素个数

第228题 汇总区间

给定一个无重复元素的有序整数数组 nums 。
返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表。也就是说,nums 的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个范围但不属于 nums 的数字 x 。
列表中的每个区间范围 [a,b] 应该按如下格式输出:
“a->b” ,如果 a != b
“a” ,如果 a == b

示例 1:

输入输出
nums = [0,1,2,4,5,7][“0->2”,“4->5”,“7”]

解释:区间范围是:
[0,2] --> “0->2”
[4,5] --> “4->5”
[7,7] --> “7”

示例 2:

输入输出
nums = [0,2,3,4,6,8,9][“0”,“2->4”,“6”,“8->9”]

解释:区间范围是:
[0,0] --> “0”
[2,4] --> “2->4”
[6,6] --> “6”
[8,9] --> “8->9”

解题思路

遍历数组,当前后数相差1时,则继续遍历,直到前后差值不为1,然后将开始遍历的位置当做左边界,遍历到的前一个位置当做右边界,如果遍历过程中左右边界相等,则直接插入这个数字做为单个字符串。

代码

// 汇总区间:数组遍历
class Solution {
    public List<String> summaryRanges(int[] nums) {
        List<String> ret = new ArrayList<String>();
        int i = 0;
        int n = nums.length;
        while (i < n) {
            int low = i;//low为左边界
            i++;
            while (i < n && nums[i] == nums[i - 1] + 1) {
                i++;
            }//当前后元素只相差1时,继续遍历
            int high = i - 1;//high为右边界
            StringBuffer temp = new StringBuffer(Integer.toString(nums[low]));
            if (low < high) {
                temp.append("->");
                temp.append(Integer.toString(nums[high]));
            }//如果左边界小于右边界,则在左边界与右边界之间加入->
            ret.add(temp.toString());//如果左边界不小于右边界,则直接加入单个字符
        }
        return ret;
    }
}

时间复杂度为O(n),n为数组长度
空间复杂度为O(1)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值