1.给定一个数组arr,求差值为k的去重数组对
public static List<List<Integer>> allPair(int[] arr, int k) {
HashSet<Integer> hashSet=new HashSet<>();
for (int i = 0; i < arr.length; i++) {
hashSet.add(arr[i]);
}
List<List<Integer>> list=new ArrayList<>();
for (Integer integer : hashSet) {
// List<Integer> listZi=new ArrayList<>();
if(hashSet.contains(integer+k)){
// listZi.add(integer);
// listZi.add(integer+k);
list.add(Arrays.asList(integer,integer+k));
}
}
return list;
}
public static void main(String[] args) {
int[] arr={3,2,5,7,0,0};
List<List<Integer>> lists = allPair(arr,2);
System.out.println(lists.toString());
}
2.给一个包含n个整数元素的集合a, 一个包含m个整数元素的集合b。
定义magic操作为, 从一个集合中取出一个元素, 放到另一个集合里, 且操作过
后每个集合的平均值都大大于于操作前。
注意以下两点:
1) 不可以把一个集合的元素取空, 这样就没有平均值了
2) 值为x的元素从集合b取出放入集合a, 但集合a中已经有值为x的元素, 则a的
平均值不变(因为集合元素不会重复) , b的平均值可能会改变(因为x被取出
了)
问最多可以进行多少次magic操作
解:A avg=100 B avg=50
只能从平均值大的里面选,且必须符合50<x<100的条件,符合条件中要选最小的,且之后要更新A和B的平均值。
// 请保证arr1无重复值、arr2中无重复值,且arr1和arr2肯定有数字
public static int maxOps(int[] arr1, int[] arr2) {
double sum1 = 0;
for (int i = 0; i < arr1.length; i++) {
sum1 += (double) arr1[i];
}
double sum2 = 0;
for (int i = 0; i < arr2.length; i++) {
sum2 += (double) arr2[i];
}
if (avg(sum1, arr1.length) == avg(sum2, arr2.length)) {
return 0;
}
int[] arrMore = null;
int[] arrLess = null;
double sumMore = 0;
double sumLess = 0;
if (avg(sum1, arr1.length) > avg(sum2, arr2.length)) {
arrMore = arr1;
sumMore = sum1;
arrLess = arr2;
sumLess = sum2;
} else {
arrMore = arr2;
sumMore = sum2;
arrLess = arr1;
sumLess = sum1;
}
Arrays.sort(arrMore);
HashSet<Integer> setLess = new HashSet<>();//要判断少的集合中是否有这个元素
for (int num : arrLess) {
setLess.add(num);
}
int moreSize = arrMore.length;//平均值大的集合还剩多少个数
int lessSize = arrLess.length;//平均值小的集合还剩多少个数
int ops = 0;//操作了多少次
for (int i = 0; i < arrMore.length; i++) {
double cur = (double) arrMore[i];
if (cur < avg(sumMore, moreSize) && cur > avg(sumLess, lessSize)
&& !setLess.contains(arrMore[i])) {
sumMore -= cur;
moreSize--;
sumLess += cur;
lessSize++;
setLess.add(cur);
ops++;
}
}
return ops;
}
public static double avg(double sum, int size) {
return sum / (double) (size);
}
public static void main(String[] args) {
int[] arr1 = { 1, 2, 5 };
int[] arr2 = { 2, 3, 4, 5, 6 };
System.out.println(maxOps(arr1, arr2));
}
3.求一个合法括号字符串的最大深度:count遇到左括号就++,count遇到右括号就–,count的最大值就是最大深度
public static int maxDeep(String s){
if(s==null||s.length()==0){
return 0;
}
char[] chars = s.toCharArray();
int count=0;
int max=0;
for (char aChar : chars) {
if(aChar=='('){
count++;
max=Math.max(count,max);
}else{
count--;
}
}
return max;
}
4.给定括号的字符串,返回有效的子串最大长度(知道思路还是未写出)
public static int maxLength(String str) {
if (str == null || str.equals("")) {
return 0;
}
char[] chas = str.toCharArray();
int[] dp = new int[chas.length];
int pre = 0;
int res = 0;
for (int i = 1; i < chas.length; i++) {
if (chas[i] == ')') {
pre = i - dp[i - 1] - 1;
if (pre >= 0 && chas[pre] == '(') {
dp[i] = dp[i - 1] + 2 + (pre > 0 ? dp[pre - 1] : 0);
}
}
res = Math.max(res, dp[i]);
}
return res;
}
5.给定一个无序栈,排成升序栈,要求只用一个辅助栈 :辅助栈一直保持降序(妨碍降序的元素扔回原栈)
public static void sort(Stack<Integer> stack){
Stack<Integer> help = new Stack<Integer>();
while(!stack.isEmpty()){
int cur=stack.pop();
if(help.isEmpty()){
help.push(cur);
}else{
while(!help.isEmpty()&&help.peek()<=cur){
stack.push(help.pop());
}
help.push(cur);
}
}
while(!help.isEmpty()){
stack.push(help.pop());
}
}
代码简化之后:
public static void sort1(Stack<Integer> stack){
Stack<Integer> help = new Stack<Integer>();
while(!stack.isEmpty()){
int cur=stack.pop();
while(!help.isEmpty()&&help.peek()<=cur){
stack.push(help.pop());
}
help.push(cur);
}
while(!help.isEmpty()){
stack.push(help.pop());
}
}
6.将给定的数转换为字符串,原则如下,1对应a,2对应b,…26对应z,例如12258可以转换为’abbeh’,‘aveh’,‘abyh’,‘lbeh’,‘lyh’,个数为5,编写一个函数,给出可以转换的不同字符串可数
(1)暴力递归
i位置出发多少种有效的:
[i]==‘0’---------0种
[i] != ‘0’---------f(i+1)
[i][i+1] <=26---------f(i+2)
public static int convertWays(int num) {
if(num<1){
return 0;
}
return process(String.valueOf(num).toCharArray(),0);
}
public static int process(char[] str, int index) {
if(index==str.length){
return 1;
}
if(str[index]=='0'){
return 0;
}
int res=process(str,index+1);
if((index+1<str.length)&&((str[index]-'0')*10+str[index+1]-'0')<27){
res+=process(str,index+2);
}
return res;
}
(2)动态规划
public static int dpways(int num) {
if (num < 1) {
return 0;
}
char[] str = String.valueOf(num).toCharArray();
int[] dp = new int[str.length + 1];
dp[str.length] = 1;
dp[str.length - 1] = str[str.length - 1] == '0' ? 0 : 1;
for (int i = str.length - 2; i >= 0; i--) {
if (str[i] == '0') {
dp[i] = 0;
} else {
dp[i] = dp[i + 1]
+ (((str[i] - '0') * 10 + str[i + 1] - '0') < 27 ? dp[i + 2]
: 0);
}
}
return dp[0];
}
7.二叉树从根节点到叶子节点路径权值和最大为多少
(1)非套路递归:pre:记录当前节点之前的路径权值和
public static int maxNum=Integer.MIN_VALUE;
public static int maxSumFeiTaoLu(Node head){
processMax(head,0);
return maxNum;
}
private static void processMax(Node node, int pre) {
if(node.left==null&&node.right==null){
maxNum=Math.max(maxNum,pre+node.value);//只有到叶子节点才比较计算
}
if(node.left!=null){
processMax(node.left,pre+node.value);
}
if(node.right!=null){
processMax(node.right,pre+node.value);
}
}
(2)套路递归:包括当前节点的树的最大路径权值和
public static int maxSumTaoLu(Node node){
return processMaxTaoLu(node);
}
private static int processMaxTaoLu(Node node){
if(node.left==null&&node.right==null){
return node.value;
}
int next=Integer.MIN_VALUE;//记录左右子树中最大的权值和(不包括当前节点)
if(node.left!=null){
next=processMaxTaoLu(node.left);
}
if(node.right!=null){
next=Math.max(next,processMaxTaoLu(node.right));
}
return node.value+next;
}