面试题整理(自用)

  • 面试题41:和为s的两个数字&和为s的连续整数序列
  • 面试题42:翻转单词顺序&左旋转字符串
  • 面试题43:n个骰子的点数
  • 面试题44:扑克牌的顺子
  • 面试题45:圆圈中剩下的最后一个数字
  • 面试题46:求1+2+3+...+n
  • 面试题47:不用加减乘除做加法
  • 面试题48:不能继承的类
  • 面试题49:把字符串转换成数字
  • 面试题50:树中两个节点的最低公共祖先

面试题41:和为s的两个数字&和为s的连续整数序列

1.输入一个递增的数组和一个数字s,在数组中找到和为s的两个数字如果有多对数字的和,输出任意一对即可
public class TwoNumberSumIsS {public static void getTwoNumberSumIsS(int[] array, int s){if (array == null || array.length < 2) return;int low = 0, high = array.length - 1;while (low < high){int pre = array[low], after = array[high];if (pre + after == s){System.out.println(pre + "/" + after);return;}else if (pre + after < s) {low++;}else {high--;}}System.out.println("不存在和为s的");}public static void main(String[] args) {int[] array = {1,2,4,7,11,15};getTwoNumberSumIsS(array, 26);}
}
2.和为s的连续整数序列
public class SumIsS {public static void getSumIsS(int s){if (s < 3) return;int small = 1, big = 2, middle = (s + 1) >> 1, sum = 3;while (small < middle){if (sum == s){printResult(small, big);}while (sum > s && small < middle){sum -= small;small++;if (sum == s) printResult(small, big);}big++;sum += big;}}private static void printResult(int small, int big) {for (int i = small; i <= big; i++){System.out.printf("%d ", i);}System.out.println();}public static void main(String[] args) {getSumIsS(100);}
}

面试题42:翻转单词顺序&左旋转字符串

1.输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变,为简单起见,标点符号和普通字符一样处理。

思路:首先翻转整个句子,然后再翻转每个单词的次序

public class Reverse {/*** 翻转字符串* @param str* @return*/public static StringBuilder reverse(StringBuilder str){if (str == null || str.length() == 0) return null;int len = str.length();for (int i = 0, j = len - 1; i < j; i++, j--){char tempI = str.charAt(i);char tempJ = str.charAt(j);str.setCharAt(i , tempJ);str.setCharAt(j, tempI);}return str;}public static String reverse(String str){if (str == null || str.length() == 0) return null;StringBuilder temp = new StringBuilder(str);temp = reverse(temp);
//        记录要翻转的单词StringBuilder word = new StringBuilder();
//        i是单词的起始位置,j是结束为止for (int i = 0, j = 0; i < str.length() && j < str.length();){if (' ' == temp.charAt(j)){temp.replace(i, j, reverse(word).toString());i = j + 1;j++;word.delete(0,word.length());}else {word.append(temp.charAt(j));j++;}}return temp.toString();}public static void main(String[] args) {System.out.printf(reverse("i love you"));}
}
2.字符串的左旋操作就是把字符串前面的若干字符转移到字符串的尾部。

思路:前面若干字符pre取出,后面若干字符after取出,返回after+left
(其实是翻转前半部分字符,再翻转后半部分字符,然后翻转整个字符)

public class LeftRotateString {public static String getLeftRotateString(String str, int number){if (str == null || str.length() == 0) return null;StringBuilder temp = new StringBuilder(str);StringBuilder word = new StringBuilder();for (int i = 0; i < number; i++){word.append(temp.charAt(i));}StringBuilder after = new StringBuilder();for (int i = number; i < str.length(); i++){after.append(temp.charAt(i));}after.append(word);return after.toString();}public static void main(String[] args) {System.out.print(getLeftRotateString("abcdef", 2));}
}

面试题43:n个骰子的点数

 把n个骰子扔在地上,所有骰子朝上的一面的点数之和为s输入n,打印出s的所有可能的值出现的概率。

思路:用数组存放每种骰子点数和出现的次数。令数组中下标为n的元素存放点数和为n的次数。我们设置循环,每个循环多投掷一个骰子,假设某一轮循环中,我们已知了各种点数和出现的次数;在下一轮循环时,我们新投掷了一个骰子,那么此时点数和为n的情况出现的次数就等于上一轮点数和为n-1,n-2,n-3,n-4,n-5,n-6的情况出现次数的总和。从第一个骰子开始,循环n次,就可以求得第n个骰子时各种点数和出现的次数。

我们这里用两个数组来分别存放本轮循环与下一轮循环的各种点数和出现的次数,不断交替使用。

public class NTouZiDeDianShu {/**** @param n 骰子个数* @param count 骰子的最大点数*/public static void getPropotity(int n, int count){if (n < 1) return;int[][] arrays = new int[2][n * count + 1];//[2]代表用两个数组交替保存,[number*maxValue+1]是指点数为所在下标时,该点数出现的总次数。//arrays[*][0]是没用的,只是为了让下标对应点数for (int i = 0; i < n * count + 1; i++){arrays[0][i] = 0;arrays[1][i] = 0;}int flag = 0;for (int i = 1; i <= count; i++){arrays[flag][i] = 1;//第一个骰子出现的情况}for (int k = 2; k <= n; k++){//当前是第几个骰子for (int i = 0; i <= k; i++){arrays[1- flag][i] = 0;//前面的数据清零}for (int i = k; i <= count * k; i++){for (int j = 1; j <= i && j <= count; j++){arrays[1 - flag][i] += arrays[flag][i - j];}}flag = 1 - flag;}double total = Math.pow((double)count, n);for (int i = n; i <= count * n; i++){double ratio = (double)arrays[flag][i] / total;System.out.println(i + ":" + String.format("%.5f", ratio));}}public static void main(String[] args) {getPropotity(2,6);}
}

面试题44:扑克牌的顺子

抽取5张牌,判断是不是一个顺子。
2-10为数字本身,A为1,J为11,Q为12,K为13,大小王可堪称任意数字。
import java.util.Arrays;public class Straight {public static boolean isStraight(int[] cards){if (cards == null || cards.length < 5) return false;boolean flag = true;Arrays.sort(cards);int zeroCount = 0, skipCount = 0;for (int i = 0; i < cards.length; i++){if (cards[i] == 0){//0表示大小王zeroCount++;}}int small = zeroCount, big = small + 1;//统计间隔数while (big < cards.length){if (cards[small] == cards[big]){flag = false;break;}skipCount += cards[big] - cards[small] - 1;small = big;big++;}if (skipCount > zeroCount) flag = false;return flag;}public static void main(String[] args) {int[] cards = {2,0,4,3,0};System.out.println(isStraight(cards));}
}

面试题45:圆圈中剩下的最后一个数字

0,1,,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字
。求出这个圆圈里剩下的最后一个数字。例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,
则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。

思路1:使用环形链表

    /*** 使用环形链表* @param circle 数据* @param m 第m个数* @return*/public static int getTheLastNumberInCircle(int[] circle, int m){if (circle == null || circle.length == 0) return -1;List<Integer> loop = new ArrayList<Integer>();for (int i = 0; i < circle.length; i++){loop.add(circle[i]);}int n = circle.length;int i = m % n - 1;if (i == -1) i = loop.size() - 1;loop.remove(i);while (loop.size() != 1){int count = 0;if (count < m) {i++;i = i % loop.size();}else break;loop.remove(i);}int res = loop.get(0);return res;}

思路2:使用数学公式

    /*** @param circle 数据* @param m 第m个数* @return*/public static int getTheLastNumberInCircle(int[] circle, int m){if (circle == null || circle.length == 0) return -1;int n = circle.length;if (n < 1 || m < 1) return -1;int last = 0;for (int i = 2; i <= n; i++) {last = (last + m) % i;}return circle[last];}

面试题46:求1+2+3+…+n

要求不能使用乘除法,for、while、if、else、switch、case以及条件判断语句

思路:使用递归

public class PlusWithoutAnything {public static int getSum(int n) {int sum = n;boolean ans = (n > 0) && ((sum += getSum(n - 1)) > 0);return sum;}public static void main(String[] args) {System.out.println(getSum(100));}
}

面试题47:不用加减乘除做加法

public class SumOfTwoNumberWithoutAnything {public static int getSum(int a, int b){int sum, carry;do{sum = a ^ b;carry = (a & b) << 1;a = sum;b = carry;}while ( (b != 0));return sum;}public static void main(String[] args) {System.out.println(getSum(1,2));}
}

面试题48:不能继承的类

//使用final关键字

面试题49:把字符串转换成数字

要考虑的东西很多,如:
1.字符串为空时
2.有符号+、-时
3.非法输入时
4.数字越界时
public class String2Number {public static int getNumber(String number){if (number == null || number.length() == 0) {System.out.println("字符串为空!");return 0;}boolean minus = false;//是否是负数int index = 0;//字符串开始的下标if (number.charAt(0) == '-') {index++;minus = true;}else if (number.charAt(0) == '+'){index++;}return getNumber(number, minus, index);}private static int getNumber(String number, boolean minus, int index) {int sign = 1;long result = 0;if (minus) sign = -1;for (int i = index; i < number.length(); i++){if (number.charAt(i) >= '0' && number.charAt(i) <= '9'){result = 10 * result + Integer.parseInt(String.valueOf(number.charAt(i)));if ((!minus && result > Integer.MAX_VALUE) || (!minus && result < Integer.MIN_VALUE)){System.out.println("越界!");return 0;}}else {System.out.println("非法输入!");return 0;}}return (int) (sign * result);}public static void main(String[] args) {System.out.println(getNumber("1230"));}
}

面试题50:树中两个节点的最低公共祖先

1.如果是二叉搜索树;

思路:最低公共祖先一定是小于一个数且大于另一个数的。如果同时小于,则在右子树中,如果同时大于则在左子树中

public class LowestCommonNode {public static Node getLowestCommonNode(Node tree, Node node1, Node node2){if (tree == null) return null;if (tree.value > node1.value && tree.value < node2.value) return tree;else if (tree.value < node1.value && tree.value < node2.value) return getLowestCommonNode(tree.right, node1, node2);else return getLowestCommonNode(tree.left, node1, node2);}public static void main(String[] args) {Node node1 = new Node(1);Node node2 = new Node(2);Node node3 = new Node(3);Node node4 = new Node(4);Node node5 = new Node(5);node2.left = node1;node2.right = node4;node4.left = node3;node4.right = node5;Node result = getLowestCommonNode(node2, node3, node5);if (result != null){System.out.println(result.value);}else {System.out.println("没找到!");}}
}
2.如果是普通的树但是有指向父节点的指针;

思路:跟着父指针构造两条链表,寻找两条链表的第一个公共节点

面试题37:两个链表的第一个公共节点

3.如果是普通的树且没有指向父节点的指针;

思路:使用辅助空间,来保存到达两个节点的链表,然后找到两个链表的公共节点

import java.util.LinkedList;
class TreeNode1{TreeNode1 node;Object value;TreeNode1[] childs;@Overridepublic String toString() {return "value=" + value;}
}
public class LowestCommonNode2 {//使用两个链表来保存根节点到所求节点的路径static LinkedList list1 = new LinkedList();static LinkedList list2 = new LinkedList();public static void main(String args[]) {TreeNode1 A = new TreeNode1();A.value = 'A';TreeNode1 B = new TreeNode1();B.value = 'B';TreeNode1 C = new TreeNode1();C.value = 'C';TreeNode1 D = new TreeNode1();D.value = 'D';TreeNode1 E = new TreeNode1();E.value = 'E';TreeNode1 F = new TreeNode1();F.value = 'F';TreeNode1 G = new TreeNode1();G.value = 'G';TreeNode1 H = new TreeNode1();H.value = 'H';TreeNode1 I = new TreeNode1();I.value = 'I';TreeNode1 J = new TreeNode1();J.value = 'J';A.childs = new TreeNode1[] {B,C};B.childs = new TreeNode1[] {D,E};D.childs = new TreeNode1[] {F,G};E.childs = new TreeNode1[] {H,I,J};/*A/ \B   C/  \D    E/ \   / | \F   G  H I  J*///找F,H节点的LCATreeNode1 lca = findLCA(F,H,A);System.out.println(lca);}private static TreeNode1 findLCA(TreeNode1 node1, TreeNode1 node2, TreeNode1 root) {getPathFromRootToNode(node1,root,list1);getPathFromRootToNode(node2,root,list2);//list1 : D -- B -- A//list2 : E -- B -- A//接下来遍历两个链表找到最近的公共节点int index = 0;int length1 = list1.size();int length2 = list2.size();int sub = length1 > length2 ? length1-length2 : length2-length1;if(length2 > length1) {LinkedList temp = list1;list1 = list2;list2 = temp;}while(index != length2 - 1) {if(((TreeNode1)list1.get(index + sub)).value == ((TreeNode1)list2.get(index)).value) {return (TreeNode1)list2.get(index);}else {index++;}}return null;}private static boolean getPathFromRootToNode(TreeNode1 node, TreeNode1 currentRoot, LinkedList list) {//找到就直接返回trueif(node.value == currentRoot.value) {return true;}//找不到就将当前节点加入路径,push是在链表的头插入的,offer是尾部list.push(currentRoot);boolean found = false;TreeNode1[] childs = currentRoot.childs;if (childs != null && childs.length > 0) {//遍历当前节点的所有子节点,在子节点里边找for (int i = 0; i < childs.length; i++) {if (found) {break;} else {found = getPathFromRootToNode(node, childs[i], list);}}}//找不到就将当前节点从路径中删除,因为是递归,当递归回来到这里的时候,当前节点一定是list的最后一个节点,即栈顶if(!found) {list.pop();}return found;}
}

剑指offer面试题(41-50)——java实现相关推荐

  1. 剑指offer——面试题41:和为S的连续整数序列

    剑指offer--面试题41:和为S的连续整数序列 Solution1:我的答案 基本思路是根据等差数列的前n项和推导出首项与项数的关系,设首项为a1a1a_1,项数为kkk,和为S" ro ...

  2. [剑指offer]面试题41:和为s的两个数字VS和为s的连续正数序列

    面试题41:和为s的两个数字VS和为s的连续正数序列 题目一:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s.如果有多对数字的和等于s,输出任意一对即可. 代码如下: b ...

  3. [剑指offer]面试题第[50]题[JAVA][第一个只出现一次的字符][哈希表][HashMap]

    [问题描述][简单] 在字符串 s 中找出第一个只出现一次的字符.如果没有,返回一个单空格. s 只包含小写字母.示例:s = "abaccdeff" 返回 "b&quo ...

  4. 剑指Offer面试题22(Java版):栈的压入、弹出序列

    题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序. 假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压栈序列,序列,4,5,3,2,1是该压栈序 ...

  5. java 打印_剑指Offer面试题20(Java版):顺时针打印矩阵

    题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字.例如:如果输入如下矩阵: 1,2,3,4 5,6,7,8 9,10,11,12 13,14,15,16 则依次打印出数字1,2,3, ...

  6. 剑指offer面试题[41]-和为s的两个数VS和为s的连续正数序列

    题目描述 题目1: 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的. 输出描述: 对应每个测试案例,输出两个数,小的先输 ...

  7. 剑指offer面试题41. 数据流中的中位数(二分查找)

    题目描述 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值. 例 ...

  8. Java详解剑指offer面试题50--第一个只出现一次的字符

    Java详解剑指offer面试题50–第一个只出现一次的字符 找出字符串中找出第一个只出现一次的字符,比如输入"abacceff",则输出'b' 要想知道某个字符是不是只出现了一次 ...

  9. [剑指offer]面试题第[68-2]题[Leetcode][第236题][JAVA][二叉搜索树的最近公共祖先][递归]

    [问题描述][中等] 235/68-1 搜索二叉树 236/68-2 二叉树 [解答思路] 递归 时间复杂度:O(N) 空间复杂度:O(N) 情况 1. , 2. , 3. , 4. 的展开写法如下. ...

  10. [剑指offer]面试题第[57]题[Leetcode][第167题][JAVA][和为s的两个数字][两数之和][HashSet][二分][双指针]

    [剑指offer]面试题第[57]题[Leetcode][第167题][第1题] 有序无序之分 题目输出不同之分 以下解法按照[剑指offer]面试题第[57]题进行题解 [问题描述][简单] 输入一 ...

最新文章

  1. eclipse左侧框不见了怎么办
  2. filezilla 定时上传_FileZilla Server安装教程 - FtpCopy数据自动备份软件(FTP定时备份)|FTP自动下载|FTP自动上传|FTP自动备份...
  3. 浅谈 温故知新——HTML5!
  4. 数据库相关的论文笔记
  5. BZOJ 3527: [ZJOI2014]力(FFT)
  6. 前端学习(1709):前端系列javascript之uniapp
  7. java怎么安装_Windows、Linux、Mac下安装JDK
  8. android applybatch,android – 使用applyBatch插入成千上万的联系人条目很慢
  9. eclipse中自定义videoview类_android控件之VideoView建立自己的播放器
  10. 住个酒店,“我”的隐私就被强制扒干净了!
  11. hbase中为何不能向表中插入数据_MySQL数据库中表记录的增、删和改操作
  12. 【Java必备技能一】支付宝手机网站支付对接
  13. dump文件 linux,Linux下快速分析DUMP文件
  14. axure 2021.04.26
  15. shell卸载 simatic_西门子软件在WIN7操作系统中安装步骤和须知
  16. SPSS 特征筛选、主成分回归
  17. 古琴【A5】良宵引-不好听
  18. MATLAB冒号表达式
  19. rtc/webrtc 2017实时音视频大会分享
  20. Python基本元素:数字、字符串和变量

热门文章

  1. 一名普通Java程序员的2022的总结和2023的展望
  2. BurpSuite抓包手机模拟器APP
  3. 青少年编程-Python之扑克牌第十幕
  4. matlab极性rz编码,单极性归零(RZ)波形及其Matlab仿真.doc
  5. 【docker知识】联合文件系统(unionFS)原理
  6. 系统安全认证设计实现
  7. Linux基本命令讲解
  8. Shader学习的基础知识( 三十一)水波效果
  9. 上汽集团、张江高科和阿里巴巴集团联合打造智己汽车
  10. OA软件如何打破信息孤岛,实现价值全面释放