}
}
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-6InrvjvL-1715579662511)]
[外链图片转存中…(img-qxHW3i6R-1715579662515)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!