提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
Java 数组算法题是程序员面试中常见的题型之一,也是日常编程实践中经常涉及到的问题。掌握 Java 数组算法可以帮助开发人员更好地处理和操作数据,并提高程序的效率和可读性。
在本篇博客中,我将介绍几个常见的 Java 数组算法问题,并提供相应的解决方案。
希望通过本篇博客的学习,您能够更加熟练地处理和操作 Java 数组数据,提高自己在程序开发领域的技能水平。
一、将有序数组转换成二叉搜索树?
难度一般
给你一个整数数组 nums
,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树
代码展示:(采用递归的方式去生成左右子树)
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return buildBST(nums,0,nums.length-1);
}
private TreeNode buildBST(int[] nums,int left,int right){
if(left>right){
return null;
}
int mid= (left+right)/2;
TreeNode root =new TreeNode(nums[mid]);
root.left=buildBST(nums,left,mid-1);
root.right=buildBST(nums,mid+1,right);
return root;
}
}
关于这题介绍:
采用递归的方法来构建一个高度平衡的二叉搜索树。由于给定的数组已经排好序,不妨以数组的中间元素作为根节点,然后将数组分成左右两个子数组,分别递归构建左右子树,最终组合起来形成完整的二叉搜索树。
具体地,假设当前递归到区间 [left, right],则中间元素应该是 nums[(left+right)/2]。然后可以递归构建左右子树,左子树对应区间 [left, mid-1],右子树对应区间 [mid+1,right]。递归下去直到区间不合法时返回空节点。时间复杂度为 O(n),其中 n 是数组长度。
二、杨辉三角
难度简单
给定一个非负整数 numRows
,生成「杨辉三角」的前 numRows
行。
在「杨辉三角」中,每个数是它左上方和右上方的数的和。
代码展示:
class Solution {
public List<List<Integer>> generate(int numRows) {
int[][] triangle=new int[numRows][numRows];
for(int i=0;i<numRows;i++){
for(int j=0;j<=i;j++){
if(j==0||j==i){
triangle[i][j]=1;
}else{
triangle[i][j]=triangle[i-1][j-1]+triangle[i-1][j];
}
}
}
List<List<Integer>> result =new ArrayList<>();
for(int i=0;i<numRows;i++){
List<Integer> row =new ArrayList<>();
for(int j=0;j<=i;j++){
row.add(triangle[i][j]);
}
result.add(row);
}
return result;
}
}
可以使用一个二维数组来生成杨辉三角,其中第 i 行有 i 个元素。首先,设置第一行的值为 1。然后,从第二行开始,每个元素都是上一行相邻两个元素之和。最后,将生成的二维数组转换成 ArrayList<ArrayList<Integer>> 类型即可 ,时间复杂度:O(n^2),其中 n 是所需生成的杨辉三角的行数。空间复杂度:O(n^2)。
三,买卖股票的最佳时机
难度简单
给定一个数组 prices
,它的第 i
个元素 prices[i]
表示一支给定股票第 i
天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0
代码展示:(小型dp)
class Solution {
public int maxProfit(int[] prices) {
int[] dp=new int[prices.length];
int minprice = prices[0];
for(int i=1;i<prices.length;i++){
minprice=Math.min(minprice,prices[i]);
dp[i]=Math.max(dp[i-1],(prices[i]-minprice));
}
return dp[prices.length-1];
}
}
对于 dp[i]
,可以选择卖出或不卖出,因此需要取它的两个可能值的最大值。
时间复杂度为 O(n),空间复杂度为 O(n)。
四,只出现一次的数字
难度简单
给你一个 非空 整数数组 nums
,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。
代码展示:(HashMap解决)
class Solution {
public int singleNumber(int[] nums) {
Map<Integer,Integer> map = new HashMap<>();
for(int i=0;i<nums.length;i++){
if(map.containsKey(nums[i])){
map.put(nums[i],2);
}else{
map.put(nums[i],1);
}
}
int result=0;
for(int key :map.keySet()){
if(map.get(key)==1){
result=key;
break;
}
}
return result;
}
}
合理利用HashMap相关知识:
HashMap 是 Java 集合框架中的一种数据结构,它用于存储键值对 (key-value pair)。HashMap 的主要作用是根据 key 查找 value,在时间复杂度为 O(1) 时间进行快速查找,这使得 HashMap 成为许多实际应用程序中经常使用的集合类型之一。
在 HashMap 中,每个键都映射到一个唯一的值上。Hash 表通过将 key 映射到索引来实现快速搜索,具体来说,Hash 表就是由指向整个 key-value 对的链表的数组(即桶)构成的。
HashMap 实现了 Map 接口,提供了排序、检索、插入和删除等方法。与其他类似实现不同的是,HashMap 允许 null 值和 null 键。同时,由于 HashMap 是非线程安全的,可以使用 Hashtable 或 ConcurrentHashMap 来替代其线程安全的版本。
常见的 HashMap 方法包括 put(key, value)
将 key 和 value 插入 HashMap,get(key)
根据 key 获取相应的 value,remove(key)
根据 key 删除 entry 等。
需要注意的是,在使用自定义对象作为 HashMap 的 key 时,需要正确实现该对象的 hashCode() 和 equals() 方法,否则会出现 Hash 冲突和无法正确查找的问题。
代码展示二:(异或实现)
class Solution {
public int singleNumber(int[] nums) {
int result =0;
for(int num : nums){
result^=num;
}
return result;
}
}
异或真的很舒服:
异或(XOR)是一种逻辑运算,通常用符号 ^
表示。异或运算的规则是:两个二进制位相同为 0,不同为 1。
例如,对于两个二进制数 1010 和 1100 进行异或运算,得到的结果为 0110。
异或运算有一些特殊性质,使它在编程中经常被使用:
- 交换律:a ^ b = b ^ a
- 结合律:(a ^ b) ^ c = a ^ (b ^ c)
- 自反性:a ^ a = 0
- 恒等式:a ^ 0 = a
其中第 1 条和第 2 条性质保证了对于多个数进行异或操作时,任意顺序得到的结果都是相同的;第 3 条性质保证了对于任意数与自己进行异或运算的结果都为 0;第 4 条性质保证了对于任意数与 0 进行异或运算的结果都为它本身。
在计算机领域,异或运算常被用于:
- 单独出现的一些数字,如找出只出现一次的元素;
- 交换两个变量的值,不需要额外引入临时变量;
- 校验数据的完整性。
五,多数元素
难度简单
给定一个大小为 n
的数组 nums
,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋
的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
代码实现:
class Solution {
public int majorityElement(int[] nums) {
Map<Integer,Integer> map = new HashMap<>();
int result = 0 ;
for(int num :nums){
if(map.containsKey(num)){
map.put(num,map.get(num)+1);
}else{
map.put(num,1);
}
if(map.get(num)>nums.length/2){
result=num;
break;
}
}
return result;
}
}
简单hash表实现
总结
上面有一些简单数组题的实现方法,希望能帮到你加深对数组的理解