2022-11-21
牛客-面试高频榜单
2 简单 3 中等 1困难
22 合并两个有序的数组
给出一个有序的整数数组 A 和有序的整数数组 B ,请将数组 B 合并到数组 A 中,变成一个有序的升序数组
注意:
1.保证 A 数组有足够的空间存放 B 数组的元素, A 和 B 中初始的元素数目分别为 m 和 n,A的数组空间大小为 m+n
2.不要返回合并的数组,将数组 B 的数据合并到 A 里面就好了,且后台会自动将合并后的数组 A 的内容打印出来,所以也不需要自己打印
- A 数组在[0,m-1]的范围也是有序的
import java.util.*;
public class Solution {
public void merge(int A[], int m, int B[], int n) {
int a = m-1;
int b = n-1;
for(int i = m+n-1 ; i >= 0 ; i--)//需要填m+n次
{
if(b<0||(a>=0&&A[a]>=B[b]))
//B数组中的数全部用完了就填A数组中的数 a数组中的数没有用完,并且A数组的数大
{
A[i]=A[a];
a--;
}
else
{
A[i]=B[b];
b--;
}
}
}
}
52 有效括号序列
给出一个仅包含字符’(‘,’)‘,’{‘,’}‘,’[‘和’]',的字符串,判断给出的字符串是否是合法的括号序列
括号必须以正确的顺序关闭,"()“和”()[]{}“都是合法的括号序列,但”(]“和”([)]"不合法。
import java.util.*;
public class Solution {
public boolean isValid (String s) {
//辅助栈
Stack<Character> st = new Stack<Character>();
//遍历字符串
for(int i = 0; i < s.length(); i++){
//遇到左小括号
if(s.charAt(i) == '(')
//期待遇到右小括号
st.push(')');
//遇到左中括号
else if(s.charAt(i) == '[')
//期待遇到右中括号
st.push(']');
//遇到左打括号
else if(s.charAt(i) == '{')
//期待遇到右打括号
st.push('}');
//必须有左括号的情况下才能遇到右括号
else if(st.isEmpty() || st.pop() != s.charAt(i))
return false;
}
//栈中是否还有元素
return st.isEmpty();
}
}
102 在二叉树中找到两个节点的最近公共祖先
给定一棵二叉树(保证非空)以及这棵树上的两个节点对应的val值 o1 和 o2,请找到 o1 和 o2 的最近公共祖先节点。
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* }
*/
public class Solution {
/**
*
* @param root TreeNode类
* @param o1 int整型
* @param o2 int整型
* @return int整型
*/
public int lowestCommonAncestor (TreeNode root, int o1, int o2) {
// write code here
//该子树没找到,返回-1
if(root == null)
return -1;
//该节点是其中某一个节点
if(root.val == o1 || root.val == o2)
return root.val;
//左子树寻找公共祖先
int left = lowestCommonAncestor(root.left, o1, o2);
//右子树寻找公共祖先
int right = lowestCommonAncestor(root.right, o1, o2);
//左子树为没找到,则在右子树中
if(left == -1)
return right;
//右子树没找到,则在左子树中
if(right == -1)
return left;
//否则是当前节点
return root.val;
}
}
17 最长回文子串
对于长度为n的一个字符串A(仅包含数字,大小写英文字母),请设计一个高效算法,计算其中最长回文子串的长度。
import java.util.*;
public class Solution {
public int fun(String s, int begin, int end){
//每个中心点开始扩展
while(begin >= 0 && end < s.length() && s.charAt(begin) == s.charAt(end)){
begin--;
end++;
}
//返回长度
return end - begin - 1;
}
public int getLongestPalindrome (String A) {
int maxlen = 1;
//以每个点为中心
for(int i = 0; i < A.length() - 1; i++)
//分奇数长度和偶数长度向两边扩展
maxlen = Math.max(maxlen, Math.max(fun(A, i, i), fun(A, i, i + 1)));
return maxlen;
}
}
54 三数之和
给出一个有n个元素的数组S,S中是否有元素a,b,c满足a+b+c=0?找出数组S中所有满足条件的三元组。
import java.util.*;
public class Solution {
public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
ArrayList<ArrayList<Integer> > res = new ArrayList<ArrayList<Integer>>();
int n = num.length;
//不够三元组
if(n < 3)
return res;
//排序
Arrays.sort(num);
for(int i = 0; i < n - 2; i++){
if(i != 0 && num[i] == num[i - 1])
continue;
//后续的收尾双指针
int left = i + 1;
int right = n - 1;
//设置当前数的负值为目标
int target = -num[i];
while(left < right){
//双指针指向的二值相加为目标,则可以与num[i]组成0
if(num[left] + num[right] == target){
ArrayList<Integer> temp = new ArrayList<Integer>();
temp.add(num[i]);
temp.add(num[left]);
temp.add(num[right]);
res.add(temp);
while(left + 1 < right && num[left] == num[left + 1])
//去重
left++;
while(right - 1 > left && num[right] == num[right - 1])
//去重
right--;
//双指针向中间收缩
left++;
right--;
}
//双指针指向的二值相加大于目标,右指针向左
else if(num[left] + num[right] > target)
right--;
//双指针指向的二值相加小于目标,左指针向右
else
left++;
}
}
return res;
}
}
6 二叉树中的最大路径和
二叉树里面的路径被定义为:从该树的任意节点出发,经过父=>子或者子=>父的连接,达到任意节点的序列。
注意:
1.同一个节点在一条二叉树路径里中最多出现一次
2.一条路径至少包含一个节点,且不一定经过根节点
给定一个二叉树的根节点root,请你计算它的最大路径和
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* }
*/
public class Solution {
/**
*
* @param root TreeNode类
* @return int整型
*/
int maxSum = Integer.MIN_VALUE;
public int maxPathSum (TreeNode root) {
// write code here
maxGain(root);
return maxSum;
}
public int maxGain(TreeNode node) {
if (node == null) {
return 0;
}
// 递归计算左右子节点的最大贡献值
// 只有在最大贡献值大于 0 时,才会选取对应子节点
int leftGain = Math.max(maxGain(node.left), 0);
int rightGain = Math.max(maxGain(node.right), 0);
// 节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值
int priceNewpath = node.val + leftGain + rightGain;
// 更新答案
maxSum = Math.max(maxSum, priceNewpath);
// 返回节点的最大贡献值
return node.val + Math.max(leftGain, rightGain);
}
}