LeetCode题解(二)0100-0199(1)

}

}

108. 将有序数组转换为二叉搜索树 (Convert Sorted Array to Binary Search Tree)

将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。

本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

示例:

给定有序数组: [-10,-3,0,5,9],

一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:

0

/ \

-3 9

/ /

-10 5

/**

  • Definition for a binary tree node.

  • public class TreeNode {

  • int val;
    
  • TreeNode left;
    
  • TreeNode right;
    
  • TreeNode(int x) { val = x; }
    
  • }

*/

class Solution {

public TreeNode sortedArrayToBST(int[] nums) {

TreeNode root;

if (nums.length == 0)

return null;

if (nums.length == 1)

root = new TreeNode(nums[0]);

else {

root = new TreeNode(nums.length / 2);

root.val = nums[nums.length/2];

int[] left = new int[nums.length / 2];

int[] right = new int[nums.length - 1 - nums.length / 2];

for (int i = 0; i < nums.length; i++) {

if (i < nums.length / 2) left[i] = nums[i];

else if (i > nums.length / 2) right[i - nums.length / 2 - 1] = nums[i];

}

root.left = sortedArrayToBST(left);

root.right = sortedArrayToBST(right);

}

return root;

}

}

110. 平衡二叉树 (Balanced Binary Tree)

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

/**

  • Definition for a binary tree node.

  • public class TreeNode {

  • int val;
    
  • TreeNode left;
    
  • TreeNode right;
    
  • TreeNode(int x) { val = x; }
    
  • }

*/

class Solution {

public boolean isBalanced(TreeNode root) {

if (root == null) return true;

if (root.left == null && root.right == null) return true;

return (Math.abs(maxDepth(root.left) - maxDepth(root.right)) < 2)

&& isBalanced(root.left) && isBalanced(root.right);

}

public int maxDepth(TreeNode root) {

if (root == null) return 0;

if (root.left == null && root.right == null) return 1;

else return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));

}

}

111. 二叉树的最小深度 (Minimum Depth of Binary Tree)

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

说明:叶子节点是指没有子节点的节点。

/**

  • Definition for a binary tree node.

  • public class TreeNode {

  • int val;
    
  • TreeNode left;
    
  • TreeNode right;
    
  • TreeNode(int x) { val = x; }
    
  • }

*/

class Solution {

public int minDepth(TreeNode root) {

if (root == null) return 0;

if (root.left == null && root.right == null) return 1;

int min = Integer.MAX_VALUE;

if (root.left != null) min = minDepth(root.left);

if (root.right != null) min = Math.min(minDepth(root.right), min);

return min + 1;

}

}

112. 路径总和 (Path Sum)

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

说明: 叶子节点是指没有子节点的节点。

示例:

给定如下二叉树,以及目标和 sum = 22,

5

/ \

4 8

/ / \

11 13 4

/ \ \

7 2 1

返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。

/**

  • Definition for a binary tree node.

  • public class TreeNode {

  • int val;
    
  • TreeNode left;
    
  • TreeNode right;
    
  • TreeNode(int x) { val = x; }
    
  • }

*/

class Solution {

public boolean hasPathSum(TreeNode root, int sum) {

if (root == null) return false;

if (root.left == null && root.right == null) return sum == root.val;

else return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);

}

}

118. 杨辉三角 (Pascal’s Triangle)

给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。

在杨辉三角中,每个数是它左上方和右上方的数的和。

示例:

输入: 5

输出:

[

[1],

[1,1],

[1,2,1],

[1,3,3,1],

[1,4,6,4,1]

]

class Solution {

public List<List> generate(int numRows) {

List<List> result = new ArrayList<List>(numRows);

if (numRows == 0) return result;

List listRow0 = new ArrayList<>(1);

listRow0.add(1);

result.add(listRow0);

for (int i = 1; i < numRows; i++) {

List listRow = new ArrayList<>(i + 1);

for (int j = 0; j < i + 1; j++) {

if (j == 0 || j == i) listRow.add(1);

else {

listRow.add(result.get(i - 1).get(j - 1) + result.get(i - 1).get(j));

}

}

result.add(listRow);

}

return result;

}

}

119. 杨辉三角 II (Pascal’s Triangle II)

给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行。

在杨辉三角中,每个数是它左上方和右上方的数的和。

示例:

输入: 3

输出: [1,3,3,1]

进阶:

你可以优化你的算法到 O(k) 空间复杂度吗?

class Solution {

// 119. 杨辉三角 II

public List getRow(int rowIndex) {

if (rowIndex == 0) {

List list0 = new ArrayList<>(1);

list0.add(1);

return list0;

} else {

List res = new ArrayList<>(rowIndex + 1);

List listPrev = getRow(rowIndex-1);

for (int i = 0; i < rowIndex + 1; i++) {

if (i == 0 || i == rowIndex) res.add(1);

else {

res.add(listPrev.get(i - 1) + listPrev.get(i));

}

}

return res;

}

}

}

121. 买卖股票的最佳时机 (Best Time to Buy and Sell Stock)

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。

注意:你不能在买入股票前卖出股票。

示例 1:

输入: [7,1,5,3,6,4]

输出: 5

解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。

注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

示例 2:

输入: [7,6,4,3,1]

输出: 0

解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

class Solution {

public int maxProfit(int[] prices) {

int minPrice = Integer.MAX_VALUE;

int maxProfit = 0;

for (int i = 0; i < prices.length; i++) {

int nowPrice = prices[i];

if (nowPrice < minPrice) minPrice = nowPrice;

else {

maxProfit = Math.max(maxProfit, nowPrice - minPrice);

}

}

return maxProfit;

}

}

125. 验证回文串 (Valid Palindrome)

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

说明:本题中,我们将空字符串定义为有效的回文串。

示例 1:

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

输出: true

示例 2:

输入: “race a car”

输出: false

class Solution {

public boolean isPalindrome(String s) {

s = s.toLowerCase().replaceAll(“[a-zA-Z^0-9]”, “”);

if (s.length() == 0) return true;

else {

char[] strs = s.toCharArray();

for (int i = 0; i < strs.length / 2; i++) {

if (strs[i] != strs[strs.length - 1 - i]) return false;

}

}

return true;

}

}

136. 只出现一次的数字 (Single Number)

[Description]

Given a non-empty array of integers, every element appears twice except for one. Find that single one.

Note:

Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

[Example]

Example 1:

Input: [2,2,1]

Output: 1

Example 2:

Input: [4,1,2,1,2]

Output: 4

[Answer]

// Runtime: 88 ms, faster than 5.02% of Java online submissions for Single Number.

// Memory Usage: 39 MB, less than 76.72% of Java online submissions for Single Number.

class Solution {

public int singleNumber(int[] nums) {

int size = nums.length;

if(size == 0) return 0;

if(size < 2) return nums[0];

ArrayList list = new ArrayList();

for (int i = 0; i < size; i++) {

int index = list.indexOf(nums[i]);

if (index >= 0)

list.remove(index);

else

list.add(nums[i]);

}

return list.get(0);

}

}

// Runtime: 7 ms, faster than 32.69% of Java online submissions for Single Number.

// Memory Usage: 39.2 MB, less than 73.94% of Java online submissions for Single Number.

class Solution {

public int singleNumber(int[] nums) {

Set set = new HashSet<>();

for(int i = 0; i < nums.length; i++) {

if(!set.contains(nums[i]))

set.add(nums[i]);

else

set.remove(nums[i]);

}

return set.iterator().next();

}

}

141. 环形链表 (Linked List Cycle)

给定一个链表,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

如果链表中存在环,则返回 true 。 否则,返回 false 。

进阶:

你能用 O(1)(即,常量)内存解决此问题吗?

/**

  • Definition for singly-linked list.

  • class ListNode {

  • int val;
    
  • ListNode next;
    
  • ListNode(int x) {
    
  •     val = x;
    
  •     next = null;
    
  • }
    
  • }

*/

public class Solution {

public boolean hasCycle(ListNode head) {

if (head == null || head.next == null) return false;

ListNode slow = head;

ListNode fast = head.next;

while (slow != fast) {

if (fast.next == null || fast.next.next == null) return false;

fast = fast.next.next;

slow = slow.next;

}

return true;

}

}

151. 翻转字符串里的单词 (Reverse Words in a String)

给定一个字符串,逐个翻转字符串中的每个单词。

说明:

无空格字符构成一个 单词 。

输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。

如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

示例 1:

输入:“the sky is blue”

输出:“blue is sky the”

示例 2:

输入:" hello world! "

输出:“world! hello”

解释:输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。

示例 3:

输入:“a good example”

输出:“example good a”

解释:如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

示例 4:

输入:s = " Bob Loves Alice "

输出:“Alice Loves Bob”

示例 5:

输入:s = “Alice does not even like bob”

输出:“bob like even not does Alice”

提示:

1 <= s.length <= 104

s 包含英文大小写字母、数字和空格 ’ ’

s 中 至少存在一个 单词

进阶:

请尝试使用 O(1) 额外空间复杂度的原地解法。

class Solution {

public String reverseWords(String s) {

String res = “”;

String word = “”;

int index = 0;

boolean start = false;

char[] chars = s.toCharArray();

while (index < chars.length) {

if (chars[index] == ’ ') {

if (start) {

if (res.equals(“”) || res.trim().length() == 0)

res = word;

else

res = word + " " + res;

start = false;

word = “”;

}

} else {

start = true;

word += chars[index];

}

index++;

}

if (!word.equals(“”)){

if (res.equals(“”) || res.trim().length() == 0)

res = word;

else

res = word + " " + res;

}

return res;

}

}

153. 寻找旋转排序数组中的最小值 (Find Minimum in Rotated Sorted Array)

假设按照升序排序的数组在预先未知的某个点上进行了旋转。例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] 。

请找出其中最小的元素。

示例 1:

输入:nums = [3,4,5,1,2]

输出:1

示例 2:

输入:nums = [4,5,6,7,0,1,2]

输出:0

示例 3:

输入:nums = [1]

输出:1

提示:

1 <= nums.length <= 5000

-5000 <= nums[i] <= 5000

nums 中的所有整数都是 唯一 的

nums 原来是一个升序排序的数组,但在预先未知的某个点上进行了旋转

class Solution {

public int findMin(int[] nums) {

for (int i = nums.length - 1; i > 0; i–) {

if (nums[i] < nums[i - 1]) return nums[i];

}

return nums[0];

}

}

154. 寻找旋转排序数组中的最小值 II (Find Minimum in Rotated Sorted Array II)

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

请找出其中最小的元素。

注意数组中可能存在重复的元素。

示例 1:

输入: [1,3,5]

输出: 1

示例 2:

输入: [2,2,2,0,1]

输出: 0

说明:

这道题是 寻找旋转排序数组中的最小值 的延伸题目。

允许重复会影响算法的时间复杂度吗?会如何影响,为什么?

class Solution {

public int findMin(int[] nums) {

for (int i = nums.length - 1; i > 0; i–) {

if (nums[i] < nums[i - 1]) return nums[i];

}

return nums[0];

}

}

155. 最小栈 (Min Stack)

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

push(x) —— 将元素 x 推入栈中。

pop() —— 删除栈顶的元素。

top() —— 获取栈顶元素。

getMin() —— 检索栈中的最小元素。

class MinStack {

/**

  • initialize your data structure here.

*/

List listData;

List listMin;

public MinStack() {

listData = new LinkedList<>();

listMin = new LinkedList<>();

}

public void push(int x) {

listData.add(x);

if (listMin.size() > 0)

listMin.add(Math.min(x, getMin()));

else listMin.add(x);

}

public void pop() {

listData.remove(listData.size() - 1);

listMin.remove(listMin.size() - 1);

}

public int top() {

return listData.get(listData.size() - 1);

}

public int getMin() {

return listMin.get(listMin.size() - 1);

}

}

/**

  • Your MinStack object will be instantiated and called as such:

  • MinStack obj = new MinStack();

  • obj.push(x);

  • obj.pop();

  • int param_3 = obj.top();

  • int param_4 = obj.getMin();

*/

160. 相交链表 (Intersection of Two Linked Lists)

编写一个程序,找到两个单链表相交的起始节点。

注意:

如果两个链表没有交点,返回 null.

在返回结果后,两个链表仍须保持原有的结构。

可假定整个链表结构中没有循环。

程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

/**

  • Definition for singly-linked list.

  • public class ListNode {

  • int val;
    
  • ListNode next;
    
  • ListNode(int x) {
    
  •     val = x;
    
  •     next = null;
    
  • }
    
  • }

*/

public class Solution {

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {

ListNode pA = headA, pB = headB;

while(pA != pB) {

pA = (pA == null ? headB : pA.next);

pB = (pB == null ? headA : pB.next);

}

return pA;

}

}

167. 两数之和 II - 输入有序数组 (Two Sum II - Input array is sorted)

给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。

函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。

说明:

返回的下标值(index1 和 index2)不是从零开始的。

你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。

示例:

输入: numbers = [2, 7, 11, 15], target = 9

输出: [1,2]

解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。

class Solution {

public int[] twoSum(int[] numbers, int target) {

int indexA = 0, indexB = 0;

for (int i = 0; i < numbers.length; i++) {

for (int j = i + 1; j < numbers.length; j++) {

if (numbers[i] + numbers[j] == target) {

indexA = i;

indexB = j;

break;

} else if (numbers[i] + numbers[j] > target)

break;

}

}

return new int[]{indexA + 1, indexB + 1};

}

}

168. Excel表列名称 (Excel Sheet Column Title)

class Solution {

public String convertToTitle(int n) {

String letters = “*ABCDEFGHIJKLMNOPQRSTUVWXYZ”;

if (n > 26) {

if (n % 26 == 0) {

return convertToTitle(n / 26 - 1) + “Z”;

} else

return convertToTitle(n / 26) + letters.charAt(n % 26);

} else return String.valueOf(letters.charAt(n));

}

}

169. 多数元素 (Majority Element)

class Solution {

public int majorityElement(int[] nums) {

if (nums.length == 1) return nums[0];

Map<Integer, Integer> map = new HashMap<>();

int maxValue = 0;

int maxKey = nums[0];

for (int n : nums) {

int value = map.containsKey(n) ? map.get(n) + 1 : 1;

map.put(n, value);

if (value > maxValue) {

maxValue = value;

maxKey = n;

if (maxValue > nums.length / 2) return maxKey;

}

}

return maxKey;

}

}

175. 组合两个表 (Combine Two Tables)

#Runtime: 225 ms, faster than 54.64% of MySQL online submissions for Combine Two Tables.

#Memory Usage: N/A

#

SELECT FirstName, LastName, City, State FROM Person LEFT JOIN Address ON Person.PersonId = Address.PersonId

#Runtime: 229 ms, faster than 47.57% of MySQL online submissions for Combine Two Tables.

#Memory Usage: N/A

#

SELECT FirstName, LastName, City, State

FROM Person LEFT JOIN Address USING(PersonId)

176. 第二高的薪水 (Second Highest Salary)

#Runtime: 137 ms, faster than 69.05% of MySQL online submissions for Second Highest Salary.

#Memory Usage: N/A

#

select max(Salary) as ‘SecondHighestSalary’

from Employee where Salary<(select max(Salary) from Employee)

181. 超过经理收入的员工 (Employees Earning More Than Their Managers)

#Runtime: 336 ms, faster than 36.93% of MySQL online submissions for Employees Earning More Than Their Managers.

#Memory Usage: N/A

#

SELECT E.Name as Employee

FROM Employee E, Employee M

WHERE E.Salary > M.Salary and E.ManagerId = M.Id

结语

  • 现在随着短视频,抖音,快手的流行NDK模块开发也显得越发重要,需要这块人才的企业也越来越多,随之学习这块的人也变多了,音视频的开发,往往是比较难的,而这个比较难的技术就是NDK里面的技术。
  • 音视频/高清大图片/人工智能/直播/抖音等等这年与用户最紧密,与我们生活最相关的技术一直都在寻找最终的技术落地平台,以前是windows系统,而现在则是移动系统了,移动系统中又是以Android占比绝大部分为前提,所以AndroidNDK技术已经是我们必备技能了。
  • 要学习好NDK,其中的关于C/C++,jni,Linux基础都是需要学习的,除此之外,音视频的编解码技术,流媒体协议,ffmpeg这些都是音视频开发必备技能,而且
  • OpenCV/OpenGl/这些又是图像处理必备知识,下面这些我都是当年自己搜集的资料和做的一些图,因为当年我就感觉视频这块会是一个大的趋势。所以提前做了一些准备。现在拿出来分享给大家。


《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
ntime: 229 ms, faster than 47.57% of MySQL online submissions for Combine Two Tables.

#Memory Usage: N/A

#

SELECT FirstName, LastName, City, State

FROM Person LEFT JOIN Address USING(PersonId)

176. 第二高的薪水 (Second Highest Salary)

#Runtime: 137 ms, faster than 69.05% of MySQL online submissions for Second Highest Salary.

#Memory Usage: N/A

#

select max(Salary) as ‘SecondHighestSalary’

from Employee where Salary<(select max(Salary) from Employee)

181. 超过经理收入的员工 (Employees Earning More Than Their Managers)

#Runtime: 336 ms, faster than 36.93% of MySQL online submissions for Employees Earning More Than Their Managers.

#Memory Usage: N/A

#

SELECT E.Name as Employee

FROM Employee E, Employee M

WHERE E.Salary > M.Salary and E.ManagerId = M.Id

结语

  • 现在随着短视频,抖音,快手的流行NDK模块开发也显得越发重要,需要这块人才的企业也越来越多,随之学习这块的人也变多了,音视频的开发,往往是比较难的,而这个比较难的技术就是NDK里面的技术。
  • 音视频/高清大图片/人工智能/直播/抖音等等这年与用户最紧密,与我们生活最相关的技术一直都在寻找最终的技术落地平台,以前是windows系统,而现在则是移动系统了,移动系统中又是以Android占比绝大部分为前提,所以AndroidNDK技术已经是我们必备技能了。
  • 要学习好NDK,其中的关于C/C++,jni,Linux基础都是需要学习的,除此之外,音视频的编解码技术,流媒体协议,ffmpeg这些都是音视频开发必备技能,而且
  • OpenCV/OpenGl/这些又是图像处理必备知识,下面这些我都是当年自己搜集的资料和做的一些图,因为当年我就感觉视频这块会是一个大的趋势。所以提前做了一些准备。现在拿出来分享给大家。

[外链图片转存中…(img-rN26vLFJ-1714907004395)]

[外链图片转存中…(img-Y28t9EmH-1714907004398)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 25
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值