剑指Offer第二版Java代码实现
- A.单例模式
- B.面试需要的基础知识
- 面试题 3:数组中重复的数字
- 面试题 4:二维数组的查找
- 面试题 5:替换空格
- 面试题 6:从尾到头打印链表
- 面试题 7:重建二叉树
- 面试题 8: 二叉树的下一个节点
- 面试题 9:用两个栈实现队列
- 面试题 10:斐波那契数列
- 面试题 10(1):求斐波那契数列的第n项
- 面试题 10 (2):青蛙跳台阶
- 面试题 11:旋转数组中最小数字
- 面试题 12:矩阵中的路径
- 面试题 13 :机械人的运动范围
- 面试题 14 :剪绳子
- 面试题 15 :二进制中 1 的个数
- C.高质量的代码
- 面试题 16:数值的整数次方
- 面试题 17:打印从1到最大的n位数
- 面试题 18: 删除链表的节点
- 面试题 18(1): 在O(1)时间删除链表的节点
- 面试题 18(2): 删除链表中重复的节点
- 面试题 19:正则表达式匹配
- 面试题 20:表示数值的字符串
- 面试题 21:调整数组顺序使奇数位于偶数前面
- 面试题 22:链表中倒数第k个节点
- 面试题 23:链表中环的入口节点
- 面试题 24:反转链表
- 面试题 25:合并两个排序的链表
- 面试题 26:树的子结构
- D.解决问题的思路
- 面试题 27:二叉树的镜像
- 面试题 28:对称的二叉树
- 面试题 29:顺时针打印矩阵
- 面试题 30:包含min函数的栈
- 面试题 31:栈的压入弹出
- 面试题 32:从上到下打印二叉树
- 面试题 32(1):不分行从上到下打印二叉树
- 面试题 32(2):分行从上到下打印二叉树
- 面试题 32(3):之字形打印二叉树
- 面试题 33: 二叉搜索树的后序遍历序列
- 面试题 34:二叉树中和为某一值的路径
- 面试题 35:复杂链表的复制
- 面试题 36:二叉搜索树与双向链表
- 面试题 37:序列化二叉树
- 面试题 38:字符串的排列
- E.优化时间和空间效率
- 面试题 39:数组中出现次数超过一半的数字
- 面试题 40:最小的k个数
- 面试题 41:数据流中的中位数
- 面试题 42:连续子数组最大和
- 面试题 43:1 ~ n 整数中 1 出现的次数
- 面试题 44:数字序列中某一位的数字
- 面试题 45:把数组排成最小的数
- 面试题 46:把数字翻译成字符串
- 面试题 47:礼物的最大值
- 面试题 48:最长不包含重复字符的子字符串
- 面试题 49:丑数
- 面试题 50:第一个只出现一次的字符
- 面试题 50(1):字符串中第一个只出现一次的字符
- 面试题 50(2):字符流中第一个只出现一次的字符
- 面试题 51:数组中的逆序对
- 面试题 52:两个链表的第一个公共节点
- F.面试中各项能力
- 面试题 53:在排序数组中查找数字
- 面试题 53(1):数字在排序数组中出现的次数
- 面试题 53(2):0 ~ n-1 中缺失的数字
- 面试题 53(3):数组中数值和下标相等的元素
- 面试题 54:二叉树的第k大个节点
- 面试题 55:二叉树的深度
- 面试题 56:数组中数字出现的次数
- 面试题 56(1):数组中只出现一次的两个数
- 面试题 56(2):数组中唯一出现一次的数字
- 面试题 56 扩展
- 面试题 57:和为 s 的数字
- 面试题 57(1):和为 s 的两个数字
- 面试题 57(2): 和为 s 的连续正数序列
- 面试题 58:翻转字符串
- 面试题 58(1): 翻转单词顺序
- 面试题 58(2): 左旋转字符串
- 面试题 59:队列的最大值
- 面试题 59(1): 滑动窗口最大值
- 面试题 59(2): 队列的最大值
- 面试题 60:n个骰子的点数
- 面试题 61:扑克牌中的顺子
- 面试题 62:圆圈中最后剩下的数字
- 面试题 63:股票的最大利润
- 面试题 64:求 1 + 2 + ... + n
- 面试题 65:不用加减乘除做加法
- 面试题 66:构建乘积数组
- G.两个面试案例
- 面试题 67:把字符串转换成整数
- 面试题 68:树中的两个节点的最低公祖先
由于本人的经验和水平有限,如有错误的地方还请不吝赐教,不胜感激!
A.单例模式
面试题 2:实现Singleton模式
public class Single1 {
private Single1(){
}
private static Single1 single1=new Single1();
public static Single1 getInstance(){
return single1;
}
}
public class Single2 {
private Single2(){
}
private static Single2 single2;
public static Single2 getInstance(){
if (single2==null){
single2=new Single2();
}
return single2;
}
}
public class Single3 {
private Single3(){
}
private static Single3 single3;
public static Single3 getInstance(){
synchronized (Single3.class){
if (single3==null){
single3=new Single3();
}
}
return single3;
}
}
public class Single4 {
private Single4(){
}
private static Single4 single4;
public static Single4 getInstance(){
if (single4==null){
synchronized (Single4.class){
if (single4==null){
single4=new Single4();
}
}
}
return single4;
}
}
public class Single5 {
private Single5(){
}
private static Single5 single5;
static {
single5=new Single5();
}
public static Single5 getInstance(){
return single5;
}
}
public class Single6 {
private Single6(){
}
private static class Nested{
private static Single6 single6;
static {
single6=new Single6();
}
}
public static Single6 getInstance(){
return Nested.single6;
}
}
B.面试需要的基础知识
面试题 3:数组中重复的数字
public class B3 {
public static void duplicate(int numbers[],int length,int duplication []){
if (numbers==null||length==0){
return;
}
Arrays.sort(numbers);
int j=0;
for (int i=0;i<length-1;i++){
if (numbers[i]==numbers[i+1]){
duplication[j]=numbers[i];
j++;
}
}
}
public static void duplicate1(int numbers[],int length,int duplication []){
if (numbers==null||length==0){
return;
}
for(int i=0;i<length;i++){
if(numbers[i]<0||numbers[i]>length-1){
return;
}
}
int k=0;
for (int i=0;i<length;i++){
while(numbers[i]!=i){
if (numbers[i]==numbers[numbers[i]]){
duplication[k]=numbers[i];
k++;
break;
}
swap(numbers,i,numbers[i]);
}
}
}
private static void swap(int[] numbers, int p, int q) {
int temp=numbers[p];
numbers[p]=numbers[q];
numbers[q]=temp;
}
public static void duplicate2(int numbers[],int length,int duplication []){
if (numbers==null||length==0){
return;
}
int start=1;
int end=length-1;
while(end>=start){
int middle=(start+end)>>1;
int count=countRange(numbers,length,start,middle);
if (end==start){
if (count>1){
duplication[0]=start;
}
break;
}
if (count>(middle-start+1)){
end=middle;
}else {
start=middle+1;
}
}
}
private static int countRange(int[] numbers, int length, int start, int end) {
if (numbers==null){
return 0;
}
int count=0;
for (int i=0;i<length;i++){
if (numbers[i]>=start&&numbers[i]<=end){
count++;
}
}
return count;
}
}
面试题 4:二维数组的查找
public class B4 {
public static boolean find(int [][]matrix,int number){
if (matrix==null||matrix.length<1||matrix[0].length<1){
return false;
}
int rows=matrix.length;
int cols=matrix[0].length;
int col=cols-1;
int row=0;
while(row>=0&&row<rows&&col>=0&&col<cols){
if (matrix[row][col]==number){
return true;
}else if (matrix[row][col]>number){
col--;
}else {
row++;
}
}
return false;
}
}
面试题 5:替换空格
public class B5 {
public String replaceSpace(StringBuffer str) {
int spacenum = 0;
for(int i=0;i<str.length();i++){
if(str.charAt(i)==' ')
spacenum++;
}
int indexold = str.length()-1;
int newlength = str.length() + spacenum*2;
int indexnew = newlength-1;
str.setLength(newlength);
for(;indexold>=0 && indexold<newlength;--indexold){
if(str.charAt(indexold) == ' '){
str.setCharAt(indexnew--, '0');
str.setCharAt(indexnew--, '2');
str.setCharAt(indexnew--, '%');
}else{
str.setCharAt(indexnew--, str.charAt(indexold));
}
}
return str.toString();
}
}
面试题 6:从尾到头打印链表
import java.util.Stack;
public class B6 {
public static class ListNode{
int val;
ListNode next;
}
public static void printListInverseIteration(ListNode root){
Stack<ListNode> stack=new Stack<>();
while (root!=null){
stack.push(root);
root=root.next;
}
ListNode temp;
while (!stack.isEmpty()){
temp=stack.pop();
System.out.println(temp.val+" ");
}
}
public static void printListInverseRecursion(ListNode root){
if (root!=null){
printListInverseRecursion(root.next);
System.out.println(root.val+" ");
}
}
}
面试题 7:重建二叉树
public class B7 {
public static class BinaryTreeNode{
int value;
BinaryTreeNode left;
BinaryTreeNode right;
}
public static BinaryTreeNode constructor(int[] preorder,int[] inorder){
if(preorder==null||inorder==null||preorder.length!=inorder.length||inorder.length<1){
return null;
}
return constructor(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
}
private static BinaryTreeNode constructor(int[] preorder, int ps, int pe, int[] inorder, int is, int ie) {
if(ps>pe){
return null;
}
int value=preorder[ps];
int index=is;
while(index<=ie&&inorder[index]!=value){
index++;
}
if(index>ie){
throw new RuntimeException("错误的输入");
}
BinaryTreeNode node=new BinaryTreeNode();
node.value=value;
node.left=constructor(preorder,ps+1,ps+index-is,inorder,is,index-1);
node.right=constructor(preorder,ps+index-is+1,pe,inorder,index+1,ie);
return node;
}
}
面试题 8: 二叉树的下一个节点
public class B8 {
private class TreeLinkNode{
int val;
TreeLinkNode left=null;
TreeLinkNode right=null;
TreeLinkNode parent=null;
TreeLinkNode(int vaa){
this.val=vaa;
}
TreeLinkNode(){}
}
private TreeLinkNode getNext(TreeLinkNode pNode){
if (pNode.right!=null){
pNode=pNode.right;
while(pNode.left!=null){
pNode=pNode.left;
}
return pNode;
}
while(pNode.parent.right!=null&&pNode.parent.right==pNode){
pNode=pNode.parent;
if ( pNode.parent==null){
return null;
}
}
return pNode.parent;
}
}
面试题 9:用两个栈实现队列
import java.util.Stack;
public class B9 {
public static class MyQueue{
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void add(int node) {
stack1.add(node);
}
public int remove() {
if(stack2.isEmpty()){
while(!stack1.isEmpty()){
stack2.push(stack1.pop());
}
}
if(stack2.isEmpty()){
throw new RuntimeException("没有更多元素了");
}
return stack2.pop();
}
}
}
面试题 10:斐波那契数列
面试题 10(1):求斐波那契数列的第n项
public class B10 {
public long fibonacci(int n){
if(n<=0){
return 0;
}
if (n==1){
return 1;
}
return fibonacci(n-1)+fibonacci(n-2);
}
public long fibonacci1(int n){
if (n<=0){
return 0;
}
if (n==1||n==2){
return 1;
}
int prePre=1;
int pre=1;
int curent=2;
for (int i=3;i<=n;i++){
curent=prePre+pre;
prePre=pre;
pre=curent;
}
return curent;
}
}
面试题 10 (2):青蛙跳台阶
public class B101 {
public long jump(int n){
if(n<=0){
return 0;
}
if (n==1){
return 1;
}
if (n==2){
return 2;
}
return jump(n-1)+jump(n-2);
}
}
面试题 11:旋转数组中最小数字
public class B11 {
public int myMin(Integer[] numbers) {
if (numbers==null||numbers.length==0){
throw new RuntimeException("错误的输入");
}
int lo=0;
int hi=numbers.length-1;
int m=0;
while(numbers[lo]>=numbers[hi]){
if (hi-lo==1){
return numbers[hi];
}
m=(lo+hi)>>1;
if (numbers[lo]==numbers[m]&&numbers[hi]==numbers[m]){
return minOrder(numbers,lo,hi);
}
if (numbers[m]>=numbers[lo]){
lo=m;
}else if (numbers[m]<=numbers[hi]){
hi=m;
}
}
return numbers[0];
}
private int minOrder(Integer[] numbers,int start,int end) {
int min=numbers[start];
for (int i=start+1;i<=end;i++){
if (numbers[i]<min){
min=numbers[i];
}
}
return min;
}
}
面试题 11 扩展1 :快速排序
public class B111 {
public void quicksort(int []a,int start,int end){
if (a==null){
return;
}
if (start<0||start>a.length-1||end<0||end>a.length-1){
return;
}
int h=start;
int e=end;
if (h>=e){
return;
}
boolean flag=true;
while (h<e){
if (a[h]>a[e]){
int temp=a[h];
a[h]=a[e];
a[e]=temp;
flag=!flag;
}
if (flag){
e--;
}else{
h++;
}
}
h++;
e--;
quicksort(a,start,e);
quicksort(a,h,end);
}
}
面试题 12:矩阵中的路径
public class B12 {
private static boolean hasPath(char[][] matrix, char[] str) {
if (matrix==null||str==null){
return false;
}
int rows=matrix.length;
int cols=matrix[0].length;
boolean[][] visited=new boolean[rows][cols];
int pathLength=0;
for (int i=0;i<rows;i++){
for (int j=0;j<cols;j++){
if (hashPathCore(matrix,str,visited,i,j,pathLength)){
return true;
}
}
}
return false;
}
private static boolean hashPathCore(char[][] matrix, char[] str, boolean[][] visited, int r, int c, int pathLength) {
int m=matrix.length;
int n=matrix[0].length;
if (pathLength==str.length){
return true;
}
boolean hasPath=false;
if (r>=0&&r<m&&c>=0&c<n&&matrix[r][c]==str[pathLength]&&visited[r][c]==false){
visited[r][c]=true;
pathLength++;
hasPath=hashPathCore(matrix, str, visited, r, c-1, pathLength)
||hashPathCore(matrix, str, visited, r, c+1, pathLength)
||hashPathCore(matrix, str, visited, r-1, c, pathLength)
||hashPathCore(matrix, str, visited, r+1, c, pathLength);
if (!hasPath){
pathLength--;
visited[r][c]=false;
}
}
return hasPath;
}
}
面试题 13 :机械人的运动范围
public class B13 {
public static int movingCount(int threshold,int rows,int cols){
if (rows<=0||cols<=0||threshold<0){
return 0;
}
boolean marked[]=new boolean[rows*cols];
return move(0,0,threshold,rows,cols,marked);
}
private static int move(int r, int c, int threshold, int rows, int cols, boolean[] marked) {
int count=0;
if (r>=0&&r<rows&&c>=0&&c<cols&&!marked[r*cols+c]&digitSum(r)+digitSum(c)<=threshold){
marked[r*cols+c]=true;
count=1+move(r, c-1, threshold, rows, cols, marked)
+move(r, c+1, threshold, rows, cols, marked)
+move(r-1, c, threshold, rows, cols, marked)
+move(r+1, c, threshold, rows, cols, marked);
}
return count;
}
private static int digitSum(int number) {
int sum=0;
while(number>0){
sum+=number%10;
number/=10;
}
return sum;
}
}
面试题 14 :剪绳子
public class B14 {
public static int maxCutting(int length){
if (length<=1){
return 0;
}
if (length==2){
return 1;
}
if (length==3){
return 2;
}
int []pro=new int[length+1];
pro[0]=0;
pro[1]=1;
pro[2]=2;
pro[3]=3;
for (int i=4;i<=length;i++){
int max=0;
for (int j=1;j<=i/2;j++){
if (max<pro[j]*pro[i-j]){
max=pro[j]*pro[i-j];
}
}
pro[i]=max;
}
return pro[length];
}
public static int maxCutting1(int length){
if (length<=1){
return 0;
}
if (length==2){
return 1;
}
if (length==3){
return 2;
}
int timesOf3=length/3;
if (length-3*timesOf3==1){
timesOf3--;
}
int timesOf2=(length-timesOf3*3)/2;
return (int)Math.pow(3,timesOf3)*(int)Math.pow(2,timesOf2);
}
}
面试题 15 :二进制中 1 的个数
public class B15 {
public int numberOf1_1(int n){
int count=0;
int flag=1;
while(flag!=0){
if ((n&flag)!=0){
count++;
}
flag=flag<<1;
}
return count;
}
public int numberOf1_2(int n){
int count=0;
while(n!=0){
if ((n&1)==1){
count++;
}
n=n>>>1;
}
return count;
}
public int numberOf1_3(int n){
int count=0;
while (n!=0){
n=(n-1)&n;
count++;
}
return count;
}
}
C.高质量的代码
面试题 16:数值的整数次方
public class C16 {
public double power(double base,int exponent){
double result;
if (exponent>0){
result=powerCore(base, exponent);
}else if (exponent<0){
if (base==0){
return 0;
}
result=1/powerCore(base, -exponent);
}else {
return 1;
}
return result;
}
private double powerCore(double base, int exponent) {
if (exponent==1){
return base;
}
if (exponent==0){
return 1;
}
double result=powerCore(base, exponent>>1);
result*=result;
if ((exponent&1)==1){
result*=base;
}
return result;
}
}
面试题 17:打印从1到最大的n位数
public class C17 {
public static void printToMax(int n){
if (n<=0){
return;
}
char [] digit=new char[n];
for (int i=0;i<n;i++){
digit[i]='0';
}
for (int i=0;i<n;i++){
while (digit[i]!='9'){
int m=n-1;
digit[m]++;
while (m>=0 && digit[m]>'9'){
digit[m]='0';
digit[--m]++;
}
printdigits(digit);
}
}
}
private static void printdigits(char[] digit) {
int k=0;
while(digit[k]=='0'){
k++;
}
for(;k<digit.length;k++){
System.out.print(digit[k]);
}
System.out.println();
}
面试题 18: 删除链表的节点
面试题 18(1): 在O(1)时间删除链表的节点
public class C18 {
public class ListNode{
int val;
ListNode next;
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
public ListNode deleteNode(ListNode head,ListNode deleteNode){
if (head==null||deleteNode==null){
return head;
}
if(deleteNode.next!=null){
ListNode nextNode=deleteNode.next;
deleteNode.val=nextNode.val;
deleteNode.next=nextNode.next;
nextNode=null;
}else if (head==deleteNode){
deleteNode=null;
head=null;
}else {
ListNode preNode=head;
while(preNode.next!=deleteNode&&preNode!=null){
preNode=preNode.next;
}
if (preNode==null){
System.out.println("需删除节点不在链表内");
return head;
}
preNode.next=null;
deleteNode=null;
}
return head;
}
}
面试题 18(2): 删除链表中重复的节点
public class C182 {
class ListNode{
int val;
ListNode next=null;
ListNode(int val,ListNode next){
this.val=val;
this.next=next;
}
}
public ListNode deleteDuplication(ListNode pHead){
if (pHead==null||pHead.next==null){
return pHead;
}
ListNode preNode=null;
ListNode curNode=pHead;
while (curNode!=null){
boolean needDelete=false;
if (curNode.next!=null && curNode.val==curNode.next.val){
needDelete=true;
}
if (!needDelete){
preNode=curNode;
curNode=curNode.next;
}else {
int dupValue=curNode.val;
ListNode toBeDel=curNode;
while (toBeDel!=null && toBeDel.val==dupValue){
toBeDel=toBeDel.next;
}
if (preNode==null){
pHead=toBeDel;
}else {
preNode.next=toBeDel;
}
curNode=toBeDel;
}
}
return pHead;
}
}
面试题 19:正则表达式匹配
public class C19 {
public boolean match(char [] str,char [] pattern){
if(str==null && pattern==null){
return false;
}
return matchCore(str,0,pattern,0);
}
private boolean matchCore(char[] str, int indexOfStr, char[] pattern, int indexOfPattern) {
if (indexOfStr==str.length && indexOfPattern==pattern.length){
return true;
}
if (indexOfStr<str.length && indexOfPattern==pattern.length){
return false;
}
if (indexOfPattern+1<pattern.length && pattern[indexOfPattern+1]=='*'){
if (indexOfStr<str.length &&
(pattern[indexOfPattern]=='.' || pattern[indexOfPattern]==str[indexOfStr])){
return matchCore(str,indexOfStr,pattern,indexOfPattern+2)||
matchCore(str,indexOfStr+1,pattern,indexOfPattern);
}else {
return matchCore(str,indexOfStr,pattern,indexOfPattern+2);
}
}
if (indexOfStr<str.length && ( pattern[indexOfPattern]=='.' || pattern[indexOfPattern]==str[indexOfStr])){
return matchCore(str,indexOfStr+1,pattern,indexOfPattern+1);
}
return false;
}
}
面试题 20:表示数值的字符串
public class C20 {
public boolean isNumeric(char[] str) {
String s=String.valueOf(str);
return s.matches("[+-]?[0-9]*(\\.[0-9]*)?([eE][+-]?[0-9]+)?");
}
public boolean isNumber(char[] str){
if(str==null||str.length==0){
return false;
}
int [] index=new int[1];
index[0]=0;
boolean isNumberic;
isNumberic=isInteger(str,index);
if(index[0]<str.length && (str[index[0]]=='.')){
index[0]++;
isNumberic=isUnsignedInteger(str,index)||isNumberic;
}
if(index[0]<str.length&&(str[index[0]]=='e'||str[index[0]]=='E')){
index[0]++;
isNumberic=isInteger(str,index)&&isNumberic;
}
if(isNumberic&&index[0]==str.length){
return true;
}else{
return false;
}
}
private boolean isInteger(char[] str, int[] index) {
if(index[0]<str.length&&(str[index[0]]=='+'||str[index[0]]=='-')){
index[0]++;
}
return isUnsignedInteger(str,index);
}
private boolean isUnsignedInteger(char[] str, int[] index) {
int start=index[0];
while(index[0]<str.length&&(str[index[0]]-'0'<=9 && str[index[0]]-'0'>=0)){
index[0]++;
}
if(index[0]>start){
return true;
}else{
return false;
}
}
}
面试题 21:调整数组顺序使奇数位于偶数前面
public class C21 {
public void reOrderArray(int [] array) {
if(array==null || array.length==0){
return;
}
int begin=0;
int end=array.length-1;
while(begin<end){
while(begin<end && (array[begin]&1)==1){
begin++;
}
while(begin<end && (array[end]&1)==0){
end--;
}
if(begin<end){
int temp=array[begin];
array[begin]=array[end];
array[end]=temp;
}
}
}
}
面试题 22:链表中倒数第k个节点
public class C22 {
public static class ListNode{
int val;
ListNode next=null;
ListNode(int val){
this.val=val;
}
}
public ListNode findKthToTail(ListNode head,int k ){
if (head==null ||k<=0){
return null;
}
int count=0;
ListNode node=head;
Stack<ListNode> stack=new Stack<>();
while(node!=null){
count++;
stack.push(node);
node=node.next;
}
if (k>count){
return null;
}else {
for (int i=1;i<=k;i++){
node=stack.pop();
}
return node;
}
}
public ListNode findKthToTail2(ListNode head,int k){
if (head==null||k<=0){
return null;
}
ListNode pAHead=head;
for (int i=1;i<k;i++){
pAHead=pAHead.next;
if (pAHead==null){
return null;
}
}
ListNode pBhead=head;
while(pAHead.next!=null){
pAHead=pAHead.next;
pBhead=pBhead.next;
}
return pBhead;
}
}
面试题 23:链表中环的入口节点
public class C23 {
public static class ListNode{
int val;
ListNode next=null;
ListNode(int val){
this.val=val;
}
}
public ListNode meetingNode(ListNode head){
if(head==null){
return null;
}
ListNode pSlow=head;
ListNode pFast=head;
while(pFast!=null){
pSlow=pSlow.next;
pFast=pFast.next;
if (pFast!=null){
pFast=pFast.next;
}
if (pSlow!=null && pFast==pSlow){
return pSlow;
}
}
return null;
}
public ListNode entryNodeOfLoop(ListNode head){
ListNode meettingNode=this.meetingNode(head);
if (meettingNode==null){
return null;
}
int count=1;
ListNode pNode1=meettingNode.next;
while(pNode1!=meettingNode){
count++;
pNode1=pNode1.next;
}
pNode1=head;
for (int i=0;i<count;i++){
pNode1=pNode1.next;
}
ListNode pNode2=head;
while(pNode1!=pNode2){
pNode1=pNode1.next;
pNode2=pNode2.next;
}
return pNode1;
}
}
面试题 24:反转链表
public class C24 {
private class ListNode{
int val;
ListNode next=null;
ListNode(int val){
this.val=val;
}
}
public ListNode reverseList1(ListNode pHead){
if (pHead==null || pHead.next==null){
return pHead;
}
ListNode pReverseHead=null;
ListNode pNode=pHead;
ListNode pPrev=null;
while(pNode!=null){
ListNode pNext=pNode.next;
if (pNext!=null){
pReverseHead=pNode;
}
pNode.next=pPrev;
pPrev=pNode;
pNode=pNext;
}
return pReverseHead;
}
public ListNode reverseList2(ListNode pHead){
if (pHead==null || pHead.next==null){
return pHead;
}
ListNode pNext=pHead.next;
ListNode reverserHead=reverseList2(pNext);
pHead.next=null;
pNext.next=pHead;
return reverserHead;
}
}
面试题 25:合并两个排序的链表
public class C25 {
private class ListNode{
int val;
ListNode next=null;
public ListNode(int val){
this.val=val;
}
public ListNode(){}
}
public ListNode merge(ListNode list1,ListNode list2){
if (list1==null){
return list2;
}
if (list2==null){
return list1;
}
if (list1.val<list2.val){
list1.next=merge(list1.next, list2);
return list1;
}else {
list2.next=merge(list1, list2.next);
return list2;
}
}
public ListNode merge2(ListNode list1,ListNode list2){
if (list1==null){
return list2;
}
if (list2==null){
return list1;
}
ListNode dumyHead=new ListNode(0);
ListNode p=dumyHead;
while(list1!=null && list2!=null){
if (list1.val<list2.val) {
p.next = list1;
list1 = list1.next;
}else {
p.next=list2;
list2=list2.next;
}
p=p.next;
}
if (list1==null){
p.next=list2;
}else {
p.next=list1;
}
return dumyHead.next;
}
}
面试题 26:树的子结构
public class C26 {
private class TreeNode{
double val;
TreeNode left=null;
TreeNode right=null;
public TreeNode(){
}
public TreeNode(int val){
this.val=val;
}
}
public boolean hasSubTree(TreeNode root1,TreeNode root2){
boolean result=false;
if (root1!=null && root2!=null){
if (root1.val==root2.val){
result=doesTree1HaveTree(root1, root2);
}
if (!result){
result=doesTree1HaveTree(root1.left, root2);
}
if (!result){
result=doesTree1HaveTree(root1.right, root2);
}
}
return result;
}
private boolean doesTree1HaveTree(TreeNode node1,TreeNode node2){
if (node2==null){
return true;
}
if (node1==null){
return false;
}
if (node1.val!=node2.val){
return false;
}
return doesTree1HaveTree(node1.left,node2.left)&&doesTree1HaveTree(node1.right,node2.right);
}
}
D.解决问题的思路
面试题 27:二叉树的镜像
public class D27 {
public class TreeNode{
int val=0;
TreeNode left=null;
TreeNode right=null;
public TreeNode(int val){
this.val=val;
}
public TreeNode(){}
}
public void mirrorRec(TreeNode root){
if (root==null){
return;
}
TreeNode tmp=root.left;
root.left=root.right;
root.right=tmp;
mirrorRec(root.left);
mirrorRec(root.right);
}
public void mirrorIterPre(TreeNode root){
LinkedList<TreeNode> stack=new LinkedList<>();
while(root!=null || !stack.isEmpty()){
stack.push(root);
while(root!=null){
if (root.left!=null || root.right!=null){
TreeNode temp=root.left;
root.left=root.right;
root.right=temp;
}
root=root.left;
}
if (!stack.isEmpty()){
root=stack.pop();
root=root.right;
}
}
}
}
面试题 28:对称的二叉树
public class D28 {
public class TreeNode{
int val=0;
TreeNode left=null;
TreeNode right=null;
public TreeNode(int val){
this.val=val;
}
}
public boolean isSysmmentrical(TreeNode pRoot){
if (pRoot==null){
return true;
}
return isEqual(pRoot.left,pRoot.right);
}
private boolean isEqual(TreeNode pRoot1, TreeNode pRoot2) {
if (pRoot1==null && pRoot2==null){
return true;
}
if (pRoot1==null || pRoot2==null){
return false;
}
return pRoot1.val==pRoot2.val && isEqual(pRoot1.left, pRoot2.right)
&& isEqual(pRoot1.right, pRoot2.left);
}
}
面试题 29:顺时针打印矩阵
public class D29 {
public static void printMatrixInCircle(int[][] numbers,int rows,int cols) {
if (numbers == null || cols < 0 || rows <= 0) {
return;
}
int start = 0;
int x = cols - 1 - start;
int y = rows - 1 - start;
while (cols>start*2 && rows>start*2){
for (int i=start;i<=y;i++){
printNumber(numbers[start][i]);
}
if (start<x){
for (int i=start+1;i<=x;i++){
printNumber(numbers[i][y]);
}
}
if (start<x && start<y){
for (int i=y-1;i>=start;i--){
printNumber(numbers[x][i]);
}
}
if (start<x-1 && start<y){
for (int i=x-1;i>start;i--){
printNumber(numbers[i][start]);
}
}
start++;
x--;
y--;
}
}
private static void printNumber(int number){
System.out.printf("%d\t",number);
}
}
面试题 30:包含min函数的栈
public class D30 {
private Stack<Integer> stack_date=new Stack<>();
private Stack<Integer> stack_min=new Stack<>();
public void push(int node){
stack_date.push(node);
if (stack_min.isEmpty() || stack_min.peek()>node){
stack_min.push(node);
}else {
stack_min.push(stack_min.peek());
}
}
public void pop(){
if (!stack_date.empty() && !stack_min.empty()){
stack_date.pop();
stack_min.pop();
}
}
}
面试题 31:栈的压入弹出
public class D31 {
public static boolean isPopOrder(int[] pushA,int[]popA){
if (pushA==null || popA==null){
return false;
}
if (popA.length!=pushA.length || pushA.length==0){
return false;
}
Stack<Integer> stack =new Stack<>();
int popIndex=0;
for (int pushIndex=0;pushIndex<pushA.length;pushIndex++){
stack.push(pushA[pushIndex]);
while(!stack.isEmpty() && stack.peek()==popA[popIndex]){
stack.pop();
popIndex++;
}
}
return stack.isEmpty();
}
}
面试题 32:从上到下打印二叉树
面试题 32(1):不分行从上到下打印二叉树
public class D32 {
public class TreeNode{
int val=0;
TreeNode left=null;
TreeNode right=null;
public TreeNode(int val){
this.val=val;
}
public TreeNode(){}
}
public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
ArrayList<Integer> array=new ArrayList();
LinkedList<TreeNode> queue=new LinkedList<>();
if (root==null){
return array;
}
queue.offer(root);
TreeNode node=null;
while(queue.size()!=0){
node=queue.poll();
array.add(node.val);
if (node.left!=null){
queue.offer(node.left);
}
if (node.right!=null){
queue.offer(node.right);
}
}
return array;
}
}
面试题 32(2):分行从上到下打印二叉树
public class D321 {
public class TreeNode{
int val=0;
TreeNode left=null;
TreeNode right=null;
public TreeNode(int val){
this.val=val;
}
public TreeNode(){}
}
public void print(TreeNode pRoot){
printTreeNode(pRoot);
}
private void printTreeNode(TreeNode root) {
if(root==null){
return;
}
LinkedList<TreeNode> queue=new LinkedList<>();
queue.offer(root);
TreeNode node=null;
int pCount=0;
int nextCount=1;
while(!queue.isEmpty()){
pCount=nextCount;
nextCount=0;
for (int i=0;i<pCount;i++){
node=queue.poll();
System.out.print(node.val+" ");
if (node.left!=null){
queue.offer(node.left);
nextCount++;
}
if (node.right!=null){
queue.offer(node.right);
nextCount++;
}
}
System.out.println();
}
}
}
面试题 32(3):之字形打印二叉树
public class D322 {
public class TreeNode{
int val=0;
TreeNode left=null;
TreeNode right=null;
public TreeNode(int val){
this.val=val;
}
public TreeNode(){}
}
public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer> > result=new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> array1=new ArrayList<Integer>();
ArrayList<Integer> array2=new ArrayList<Integer>();
if (pRoot==null){
return result;
}
Stack<TreeNode> stack1=new Stack<>();
Stack<TreeNode> stack2=new Stack<>();
TreeNode node=null;
stack1.push(pRoot);
while(!stack1.isEmpty() || !stack2.isEmpty()){
array1=new ArrayList<Integer>();
array2=new ArrayList<Integer>();
while(!stack1.isEmpty()){
node=stack1.pop();
array1.add(node.val);
if (node.left!=null){
stack2.push(node.left);
}
if (node.right!=null){
stack2.push(node.right);
}
}
while (!stack2.isEmpty()){
node=stack2.pop();
array2.add(node.val);
if (node.right!=null){
stack1.push(node.right);
}
if (node.left!=null){
stack1.push(node.left);
}
}
if(!array1.isEmpty()){
result.add(array1);
}
if(!array2.isEmpty()){
result.add(array2);
}
}
return result;
}
}
面试题 33: 二叉搜索树的后序遍历序列
public class D33 {
public boolean verifySequenceOfBST(int[] sequence){
if (sequence==null || sequence.length<=0){
return false;
}
return verifyCore(sequence,0,sequence.length-1);
}
private boolean verifyCore(int[] sequence, int start, int end) {
if (start>=end){
return true;
}
int mid=start;
while (sequence[mid]<sequence[end]){
mid++;
}
for (int i=mid;i<end;i++){
if (sequence[i]<sequence[end]){
return false;
}
}
return verifyCore(sequence, start, mid-1)
&& verifyCore(sequence,mid, end-1);
}
}
面试题 34:二叉树中和为某一值的路径
public class D34 {
public class TreeNode{
int val=0;
TreeNode left=null;
TreeNode right=null;
public TreeNode(){
}
public TreeNode(int val){
this.val=val;
}
}
ArrayList<ArrayList<Integer>> result=new ArrayList();
ArrayList<Integer> list=new ArrayList<>();
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
if(root==null){
return result;
}
list.add(root.val);
target-=root.val;
if (target==0 && root.left==null && root.right==null){
result.add(new ArrayList<Integer>(list));
}else {
FindPath(root.left,target);
FindPath(root.right,target);
}
list.remove(list.size()-1);
return result;
}
}
面试题 35:复杂链表的复制
public class D35 {
public class ComplexListNode{
String val;
ComplexListNode sibling=null;
ComplexListNode next=null;
ComplexListNode(String val){
this.val=val;
}
ComplexListNode(){}
}
public ComplexListNode cloneList(ComplexListNode head){
cloneNodes(head);
connectionSiblingNodes(head);
return reconnectNodes(head);
}
private void cloneNodes(ComplexListNode head) {
ComplexListNode pNode=head;
while(pNode!=null){
ComplexListNode cloneNode=new ComplexListNode(pNode.val+"’");
cloneNode.next=pNode.next;
pNode.next=cloneNode;
pNode=cloneNode.next;
}
}
private void connectionSiblingNodes(ComplexListNode head) {
ComplexListNode pNode=head;
while(pNode!=null){
if (pNode.sibling!=null){
pNode.next.sibling=pNode.sibling.next;
}
pNode=pNode.next.next;
}
}
private ComplexListNode reconnectNodes(ComplexListNode head) {
ComplexListNode cloneHead=null;
ComplexListNode cloneNode=null;
ComplexListNode pNode=head;
if (head!=null){
cloneHead=head.next;
cloneNode=head.next;
pNode.next=cloneNode.next;
pNode=pNode.next;
}
while(pNode!=null){
cloneNode.next=pNode.next;
cloneNode=cloneNode.next;
pNode.next=cloneNode.next;
pNode=pNode.next;
}
return cloneHead;
}
}
面试题 36:二叉搜索树与双向链表
public class D36 {
public class TreeNode{
int val=0;
TreeNode left=null;
TreeNode right=null;
public TreeNode(int val){
this.val=val;
}
public TreeNode(){}
}
public TreeNode Convert(TreeNode pRootOfTree) {
if(pRootOfTree==null){
return pRootOfTree;
}
TreeNode lastNode=null;
TreeNode firstNode=convertCore(pRootOfTree,lastNode);
while(firstNode.left!=null){
firstNode=firstNode.left;
}
return firstNode;
}
private TreeNode convertCore(TreeNode root,TreeNode lastNode) {
if(root==null){
return lastNode;
}
TreeNode currentNode=root;
if(currentNode.left!=null){
lastNode=convertCore(currentNode.left,lastNode);
}
currentNode.left=lastNode;
if(lastNode!=null){
lastNode.right=currentNode;
}
lastNode=currentNode;
if(currentNode.right!=null){
lastNode=convertCore(currentNode.right,lastNode);
}
return lastNode;
}
}
面试题 37:序列化二叉树
public class D37 {
private class TreeNode{
int val=0;
TreeNode left=null;
TreeNode right=null;
public TreeNode(int val){
this.val=val;
}
public TreeNode(){
}
}
public String serialize(TreeNode node){
StringBuilder sb=new StringBuilder();
if (node==null){
sb.append("$,");
}else {
sb.append(node.val+",");
sb.append(serialize(node.left));
sb.append(serialize(node.right));
}
return sb.toString();
}
private int index=0;
public TreeNode deserialize(String str) {
TreeNode node=null;
if (str==null || str.length()==0){
return null;
}
int start=index;
while(str.charAt(index)!=','){
index++;
}
if (!str.substring(start,index).equals("$")){
node=new TreeNode(Integer.parseInt(str.substring(start,index)));
index++;
node.left=deserialize(str);
node.right=deserialize(str);
}else {
index++;
}
return node;
}
}
面试题 38:字符串的排列
public class D38 {
public ArrayList<String> permutation(String str){
ArrayList<String> list=new ArrayList<>();
if (str==null || str.length()==0){
return list;
}
permutationCore(str.toCharArray(),1,list);
Collections.sort(list);
return list;
}
private void permutationCore(char[] strArray, int index, ArrayList<String> list) {
if (index==strArray.length-1){
list.add(String.valueOf(strArray));
}else {
for (int i=index;i<strArray.length;i++){
char temp=strArray[index];
strArray[index]=strArray[i];
strArray[i]=temp;
permutationCore(strArray, index+1, list);
temp=strArray[index];
strArray[index]=strArray[i];
strArray[i]=temp;
}
}
}
}
E.优化时间和空间效率
面试题 39:数组中出现次数超过一半的数字
public class E39 {
public int MoreThanHalfNum_Solution(int [] array) {
HashMap<Integer,Integer> hm=new HashMap();
for(int i=0;i<array.length;i++){
if(hm.containsKey(array[i])){
hm.put(array[i],hm.get(array[i])+1);
}else{
hm.put(array[i],1);
}
}
for(Entry<Integer,Integer> entry:hm.entrySet()){
if(entry.getValue()>array.length>>1){
return entry.getKey();
}
}
return 0;
}
}
面试题 40:最小的k个数
public class E40 {
public ArrayList<Integer> GetLeastNumbers(int[] input,int k){
ArrayList<Integer> list=new ArrayList<>();
if (input==null || input.length==0 || k>input.length || k<0){
return list;
}
PriorityQueue<Integer> maxHeap=new PriorityQueue(Comparator.reverseOrder());
for (int i:input){
maxHeap.offer(i);
if (maxHeap.size()>k){
maxHeap.poll();
}
}
list.addAll(maxHeap);
return list;
}
}
面试题 41:数据流中的中位数
public class E41 {
private PriorityQueue<Integer> minHeap=new PriorityQueue<>();
private PriorityQueue<Integer> maxHeap=new PriorityQueue<>(Comparator.reverseOrder());
public void insert(Integer num){
if (((minHeap.size()+maxHeap.size())&1)==0){
if (!maxHeap.isEmpty() && maxHeap.peek()>num){
maxHeap.offer(num);
num=maxHeap.poll();
}
minHeap.offer(num);
}else {
if(!minHeap.isEmpty()&&minHeap.peek()<num){
minHeap.offer(num);
num=minHeap.poll();
}
maxHeap.offer(num);
}
}
public Integer getMedian(){
if (minHeap.size()+maxHeap.size()==0){
throw new RuntimeException();
}
Integer m;
if(((minHeap.size()+maxHeap.size())&1)==0){
int max=maxHeap.peek();
int min=minHeap.peek();
m=(max+min)>>1;
}else{
m=minHeap.peek();
}
return m;
}
}
面试题 42:连续子数组最大和
public class E42 {
boolean invalidInput=false;
private int findGreatestSumOfSubarray(int [] array){
if (array==null || array.length<=0){
invalidInput=true;
return 0;
}
invalidInput=false;
int sum=array[0];
int maxSum=array[0];
for (int i=1; i<array.length;i++){
if (sum<0){
sum=array[i];
}else {
sum+=array[i];
}
if (sum>maxSum){
maxSum=sum;
}
}
return maxSum;
}
}
面试题 43:1 ~ n 整数中 1 出现的次数
public class E43 {
public int numberOfBetweenl(int n){
int count=0;
for (int i=1;i<=n;i*=10){
int high=n/(i*10);
int low=n%i;
int cur=(n/i)%10;
if (cur==0){
count+=high*i;
}else if (cur==1){
count+=high*i+(low+1);
}else {
count+=(high+1)*i;
}
}
return count;
}
}
面试题 44:数字序列中某一位的数字
public class E44 {
public int digitAtIndex(int index) {
if(index<0)
return -1;
int m=1;
while(true) {
int numbers=numbersOfIntegers(m);
if(index<numbers*m){
return getDigit(index,m);
}
index-=numbers*m;
m++;
}
}
private int numbersOfIntegers(int m) {
if(m==1)
return 10;
return (int) (9*Math.pow(10, m-1));
}
private int getDigit(int index, int m) {
int number=getFirstNumber(m)+index/m;
int indexFromRight = m-index%m;
for(int i=1;i<indexFromRight;i++){
number/=10;
}
return number%10;
}
private int getFirstNumber(int m) {
if(m==1)
return 0;
return (int) Math.pow(10, m-1);
}
}
面试题 45:把数组排成最小的数
public class E45 {
public String printMinNumber(int [] numbers){
if(numbers==null || numbers.length<=0){
return "";
}
ArrayList<String> list=new ArrayList<>();
for (int number: numbers){
list.add(String.valueOf(number));
}
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
String a=o1+o2;
String b=o2+o1;
return a.compareTo(b);
}
});
StringBuffer sb=new StringBuffer();
for (String str: list){
sb.append(str);
}
return sb.toString();
}
}
面试题 46:把数字翻译成字符串
public class E46 {
public int getTranslationCount(int n){
if(n<0){
return 0;
}
return count(String.valueOf(n));
}
private int count(String num) {
int len=num.length();
int []counts=new int[len];
counts[len-1]=1;
for (int i=len-2;i>0;i--){
int high=num.charAt(i)-'0';
int low=num.charAt(i+1)-'0';
int combineNum=high*10+low;
if (combineNum>=10 && combineNum<=25){
if (i==len-2){
counts[i]=counts[i+1]+1;
}else{
counts[i]=counts[i+1]+counts[i+2];
}
}else {
counts[i]=counts[i+1];
}
}
return counts[0];
}
}
面试题 47:礼物的最大值
public class E47 {
public int maxValueOfGifts(int [][] values){
if(values==null||values.length<=0||values[0].length<=0){
return 0;
}
int rows=values.length;
int cols=values[0].length;
int [][] maxValue=new int[rows][cols];
for(int i=0;i<rows;i++){
for (int j=0;j<cols;j++){
int left=0;
int above=0;
if (i>0){
above=maxValue[i-1][j];
}
if (j>0){
left=maxValue[i][j-1];
}
maxValue[i][j]=Math.max(above,left)+values[i][j];
}
}
return maxValue[rows-1][cols-1];
}
}
面试题 48:最长不包含重复字符的子字符串
public class E48 {
private int findLongestSubstring(String str){
int curLen=0;
int maxLen=0;
int []position=new int[26];
for(int i=0;i<26;i++){
position[i]=-1;
}
for(int i=0;i<str.length();i++){
char t=str.charAt(i);
int preIndex=position[t-'a'];
int d=i-preIndex;
if(preIndex==-1||d>curLen){
curLen++;
}else{
curLen=d;
}
position[str.charAt(i)-'a']=i;
if(curLen>maxLen){
maxLen=curLen;
}
}
return maxLen;
}
}
面试题 49:丑数
public class E49 {
private int getUglyNumberSo1(int index){
if(index<=0){
return 0;
}
int number=0;
int uglyCount=0;
while(uglyCount<index){
++number;
if(isUgly(number)){
++uglyCount;
}
}
return number;
}
private boolean isUgly(int number) {
while(number%2==0){
number/=2;
}
while(number%3==0){
number/=3;
}
while(number%5==0){
number/=5;
}
return number==1?true:false;
}
public int getUglyNumberSo2(int index) {
if (index <= 0) {
return 0;
}
int t2 = 0;
int t3 = 0;
int t5 = 0;
int[] res = new int[index];
res[0] = 1;
for (int i = 1; i < index; i++) {
int m2 = res[t2] * 2;
int m3 = res[t3] * 3;
int m5 = res[t5] * 5;
res[i] = Math.min(m2, Math.min(m3, m5));
if (res[i] == m2) {
t2++;
}
if (res[i] == m3) {
t3++;
}
if (res[i] == m5) {
t5++;
}
}
return res[index - 1];
}
}
面试题 50:第一个只出现一次的字符
面试题 50(1):字符串中第一个只出现一次的字符
public class E50 {
public char firstNoRepeatringChar(String str){
if(str==null){
return '\0';
}
int [] repetitions=new int[256];
for(int i=0;i<str.length();i++){
int loc=str.charAt(i);
repetitions[loc]+=1;
}
for(int i=0;i<str.length();i++){
int loc=str.charAt(i);
if(repetitions[loc]==1){
return (char)loc;
}
}
return '\0';
}
}
面试题 50(2):字符流中第一个只出现一次的字符
public class E501 {
private int[] occur = new int[256];
private int index = 1;
public void Insert(char ch) {
if (occur[ch] == 0) {
occur[ch] = index;
} else {
occur[ch] = -2;
}
index++;
}
public char FirstAppearingOnce() {
char ch = '#';
int min = Integer.MAX_VALUE;
for (int i = 0; i < 256; i++) {
if (occur[i] > 0 && occur[i] < min) {
ch = (char) i;
min = occur[i];
}
}
return ch;
}
面试题 51:数组中的逆序对
public class E51 {
public static int inversePairs(int [] array){
if(array==null||array.length<=0){
return 0;
}
return getCount(array,0,array.length-1);
}
private static int getCount(int[] array, int start, int end) {
if(start>=end){
return 0;
}
int mid=(end+start)>>1;
int left=getCount(array,start,mid);
int right=getCount(array,mid+1,end);
int count=0;
int i=mid;
int j=end;
int [] tmp=new int[end-start+1];
int k=end-start;
while(i>=start && j>=mid+1){
if(array[i]>array[j]){
count+=(j-mid);
tmp[k--]=array[i--];
}else{
tmp[k--]=array[j--];
}
}
while(i>=start){
tmp[k--]=array[i--];
}
while(j>=mid+1){
tmp[k--]=array[j--];
}
for(k=0;k<tmp.length;k++){
array[k+start]=tmp[k];
}
return count+left+right;
}
}
面试题 52:两个链表的第一个公共节点
public class E52 {
public class ListNode{
int val;
ListNode next=null;
ListNode(int val){
this.val=val;
}
ListNode(){}
}
public ListNode findFirstCommonNode(ListNode pHead1,ListNode pHead2){
Stack<ListNode> s1=new Stack<>();
Stack<ListNode> s2=new Stack<>();
if (pHead1==null || pHead2==null){
return null;
}
while(pHead1!=null){
s1.push(pHead1);
pHead1=pHead1.next;
}
while(pHead2!=null){
s2.push(pHead2);
pHead2=pHead2.next;
}
ListNode tmp=null;
while(!s1.empty()){
ListNode l1=s1.peek();
ListNode l2=s2.peek();
if (l1==l2){
tmp=s1.pop();
s2.pop();
}
}
return tmp;
}
public ListNode findFirstCommonNode1(ListNode pHead1,ListNode pHead2){
int length1=getLength(pHead1);
int length2=getLength(pHead2);
int size=length1-length2;
ListNode longNode=pHead1;
ListNode shortNode=pHead2;
if (size<0){
longNode=pHead2;
shortNode=pHead1;
}
for (int i=0;i<size;i++){
longNode=longNode.next;
}
while (longNode!=null && longNode!=shortNode){
longNode=longNode.next;
shortNode=shortNode.next;
}
return longNode;
}
private int getLength(ListNode pHead){
int len=0;
while(pHead!=null){
len++;
pHead=pHead.next;
}
return len;
}
}
F.面试中各项能力
面试题 53:在排序数组中查找数字
面试题 53(1):数字在排序数组中出现的次数
public class F53 {
public int GetNumberOfK(int[] array, int k) {
int first = binarySearch(array, k);
int last = binarySearch(array, k + 1);
return last - first;
}
private int binarySearch(int[] array, int K) {
int l = 0;
int h = array.length;
while (l < h) {
int m = l + (h - l) / 2;
if (array[m] >= K){
h = m;
}else{
l = m + 1;
}
}
return l;
}
}
面试题 53(2):0 ~ n-1 中缺失的数字
public class F531 {
public int getMissingNumber(int [] arr){
if (arr==null || arr.length<=0){
return -1;
}
int low=0;
int high=arr.length-1;
while(low<=high){
int mid=(low+high)>>1;
if (arr[mid]!=mid){
if (mid==0 || arr[mid-1]==mid-1){
return mid;
}else {
high=mid+1;
}
}else {
low=mid+1;
}
}
return -1;
}
}
面试题 53(3):数组中数值和下标相等的元素
public class F532 {
private int getNumberSameAsIndex(int [] arr){
if(arr==null||arr.length<=0){
return -1;
}
int low=0;
int high=arr.length-1;
while(low<=high){
int mid=(low+high)>>1;
if(arr[mid]>mid){
high=mid-1;
}else if(arr[mid]<mid){
low=mid+1;
}else{
return mid;
}
}
return -1;
}
}
面试题 54:二叉树的第k大个节点
public class F54 {
public class TreeNode{
int val=0;
TreeNode left=null;
TreeNode right=null;
public TreeNode(int val){
this.val=val;
}
public TreeNode(){
}
}
public TreeNode findKthNode(TreeNode root,int k){
if (root == null || k<=0) {
return null;
}
Stack<TreeNode> stack=new Stack<>();
int count=0;
while(root!=null || !stack.isEmpty()){
while(root!=null){
stack.push(root);
root=root.left;
}
if (!stack.isEmpty()){
root=stack.pop();
if (++count==k){
return root;
}
root=root.right;
}
}
return null;
}
}
面试题 55:二叉树的深度
public class F55 {
public class TreeNode{
int val=0;
TreeNode left=null;
TreeNode right=null;
public TreeNode(int val){
this.val=val;
}
public TreeNode(){
}
}
public int treeDepth(TreeNode root){
if (root==null){
return 0;
}
int left=treeDepth(root.left);
int right=treeDepth(root.right);
return left>right?(left+1):(right+1);
}
}
面试题 56:数组中数字出现的次数
面试题 56(1):数组中只出现一次的两个数
public static void findNumsAppearOnce(int [] array,int num1[] , int num2[]) {
if(array == null || array.length <= 1){
num1[0] = num2[0] = 0;
return;
}
int len = array.length, index = 0, sum = 0;
for(int i = 0; i < len; i++){
sum ^= array[i];
}
for(index = 0; index < 32; index++){
if((sum & (1 << index)) != 0) {
break;
}
}
for(int i = 0; i < len; i++){
if((array[i] & (1 << index))!=0){
num2[0] ^= array[i];
}else{
num1[0] ^= array[i];
}
}
}
面试题 56(2):数组中唯一出现一次的数字
public static int find1From3(int[] a){
int[] bits = new int[32];
int len = a.length;
for(int i = 0; i < len; i++){
for(int j = 0; j < 32; j++){
bits[j] = bits[j] + ( (a[i]>>>j) & 1);
}
}
int res = 0;
for(int i = 0; i < 32; i++){
if(bits[i] % 3 !=0){
res = res | (1 << i);
}
}
return res;
}
面试题 56 扩展
public static int find1From2(int[] a){
int len = a.length, res = 0;
for(int i = 0; i < len; i++){
res = res ^ a[i];
}
return res;
}
面试题 57:和为 s 的数字
面试题 57(1):和为 s 的两个数字
public ArrayList<Integer> FindNumberWithSum(int[] array,int sum){
ArrayList<Integer> list=new ArrayList<>();
int start=0;
int end=array.length-1;
while(start<end){
if (array[start]+array[end]>sum){
end--;
}else if (array[start]+array[end]<sum){
start++;
}else {
list=new ArrayList<Integer>();
list.add(array[start]);
list.add(array[end]);
break;
}
}
return list;
}
面试题 57(2): 和为 s 的连续正数序列
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer> > result = new ArrayList<>();
int plow = 1,phigh = 2;
while(phigh > plow){
int cur = (plow + phigh) * (phigh - plow + 1) / 2;
if(cur == sum){
ArrayList<Integer> list = new ArrayList<>();
for(int i=plow;i<=phigh;i++){
list.add(i);
}
result.add(list);
plow++;
}else if(cur < sum){
phigh++;
}else{
plow++;
}
}
return result;
}
面试题 58:翻转字符串
面试题 58(1): 翻转单词顺序
public String reverseSentence(String str) {
if(str.length()==0 || str.trim().equals("")){
return str;
}
String[] str1 = str.split(" ");
StringBuffer sb = new StringBuffer();
for(int i=str1.length-1;i>=0;i--){
if(i==0){
sb.append(str1[i]);
}else{
sb.append(str1[i]+" ");
}
}
return sb.toString();
}
public String reverseSentence2(String str) {
if (str == null || "".equals(str)){
return "";
}
char[] targetArr = str.toCharArray();
int begin = 0;
int end = targetArr.length-1;
char[] reverseArr = reverse(targetArr, begin, end);
end = 0;
begin = 0;
while(end < targetArr.length){
if (reverseArr[end] == ' '){
reverse(targetArr,begin,--end);
begin = ++end;
end = ++begin;
}else if (end== targetArr.length -1){
reverse(targetArr,begin,end);
begin = ++end;
end = ++begin;
} else if(reverseArr[begin] == ' '){
++begin;
++end;
}else {
++end;
}
}
return String.valueOf(reverseArr);
}
private char[] reverse(char[] arr, int begin, int end) {
while (begin < end) {
char temp = arr[begin];
arr[begin] = arr[end];
arr[end] = temp;
++begin;
--end;
}
return arr;
}
面试题 58(2): 左旋转字符串
public String leftRotateString(String chars ,int num){
if(chars==null||chars.length()<=0){
return chars;
}
char [] tmp=chars.toCharArray();
tmp=reverseSb(chars,0,num-1);
tmp=reverseSb(String.valueOf(tmp), num,chars.length()-1);
tmp=reverseSb(String.valueOf(tmp), 0,chars.length()-1);
return String.valueOf(tmp);
}
private char [] reverseSb(String chars, int start, int end) {
char[] ct=chars.toCharArray();
while(start<end){
char tmp=ct[start];
ct[start]=ct[end];
ct[end]=tmp;
start++;
end--;
}
return ct;
}
public String leftRotateString2(String str,int n) {
if(str.equals("")){
return str;
}
if (n>str.length() || n<0){
return null;
}
return str.substring(n,str.length()) + str.substring(0,n);
}
面试题 59:队列的最大值
面试题 59(1): 滑动窗口最大值
public int[] maxInWindows(int [] num,int size){
if(num==null||num.length<=0||size<=0||size>num.length){
return null;
}
int [] max=new int[num.length-(size-1)];
ArrayDeque<Integer> indexDeque=new ArrayDeque<>();
for(int i=0;i<size-1;i++){
while(!indexDeque.isEmpty()&&num[i]>num[indexDeque.getFirst()]){
indexDeque.removeLast();
}
indexDeque.addLast(i);
}
int j=0;
for(int i=size-1;i<num.length;i++){
while(!indexDeque.isEmpty()&&num[i]>num[indexDeque.getLast()]){
indexDeque.removeLast();
}
if(!indexDeque.isEmpty()&&(i-indexDeque.getFirst())>=size){
indexDeque.removeFirst();
}
indexDeque.addLast(i);
max[j++]=num[indexDeque.getFirst()];
}
return max;
}
面试题 59(2): 队列的最大值
private Deque<Integer> maxDeque=new LinkedList<>();
private Deque<Integer> dataDeque=new LinkedList<>();
public void push_back(int number){
dataDeque.offerLast(number);
while(!maxDeque.isEmpty()&&maxDeque.getLast()<number){
maxDeque.removeLast();
}
maxDeque.addLast(number);
}
public void pop_front(){
if(dataDeque.isEmpty()){
throw new RuntimeException("队列已空");
}
int i=dataDeque.pollFirst();
if(i==maxDeque.getFirst()){
maxDeque.removeFirst();
}
}
public int max(){
if(maxDeque==null){
System.out.println("队列为空,无法删除");
return 0;
}
return maxDeque.getFirst();
}
面试题 60:n个骰子的点数
public class F60 {
private int sideNum=6;
public void printProbability(int n){
if(n<1){
return;
}
int maxVal=n * sideNum;
int [] probabilities=new int[maxVal-n+1];
getPro(n,n,0,probabilities);
int total=(int)Math.pow(sideNum,n);
for(int i=n;i<=maxVal;i++){
System.out.println(n+"个骰子,朝上一面的点数之和"+"s是"+i+"个点的频率是:"+probabilities[i-n]+"/"+total);
}
}
private void getPro(int original , int cur,int sum,int [] p){
if(cur==0){
p[sum-original]++;
return;
}
for(int i=1;i<=sideNum;i++){
getPro(original,cur-1,sum+i,p);
}
}
}
面试题 61:扑克牌中的顺子
public class F61 {
public boolean isCount(int[] numbers){
if(numbers==null||numbers.length<=0){
return false;
}
Arrays.sort(numbers);
int jokerCount=0;
for (int i=0;i<4;i++){
if (numbers[i]==0){
jokerCount++;
}
}
int gap=0;
for (int i=numbers.length-1;i>jokerCount;i--){
if (numbers[i]==numbers[i-1]){
return false;
}
gap+=numbers[i]-numbers[i-1]-1;
}
return gap<=jokerCount;
}
}
面试题 62:圆圈中最后剩下的数字
public class F62 {
public int last(int n,int m){
if (n<0 || m<=0){
return -1;
}
List<Integer> list=new LinkedList<>();
for (int i=0;i<n;i++){
list.add(i);
}
int p=0;
while (list.size()>1){
for (int k=0;k<m-1;k++){
p++;
if (p==list.size()){
p=0;
}
}
list.remove(p);
if (p==list.size()){
p=0;
}
}
return list.get(0);
}
public int last1(int n,int m){
if (n<=0 || m<=0){
return -1;
}
int f=0;
for (int i=2;i<=n;i++){
f=(f+m)%i;
}
return f;
}
}
面试题 63:股票的最大利润
public class F63 {
public int getMaxDiff(int[] prices){
if (prices==null || prices.length<2){
return 0;
}
int min=prices[0];
int maxDiff=0;
int curDiff=0;
for (int i=1;i<prices.length;i++){
if (prices[i]<min){
min=prices[i];
}
curDiff=prices[i]-min;
if (curDiff>maxDiff){
maxDiff=curDiff;
}
}
return maxDiff;
}
}
面试题 64:求 1 + 2 + … + n
public class F64 {
public int getSum(int n){
int sum=n;
boolean flag=(n>1) && ( (sum+=getSum(n-1)) > 0);
return sum;
}
public int getSum2(int n){
return ( (int)Math.pow(n,2) + n )>>1;
}
}
面试题 65:不用加减乘除做加法
public class F65 {
public int add(int num1,int num2){
while(num2!=0){
int sum=num1^num2;
int carrry=(num1&num2)<<1;
num1=sum;
num2=carrry;
}
return num1;
}
public int add2(int num1,int num2){
BigDecimal n1=new BigDecimal(num1);
BigDecimal n2=new BigDecimal(num2);
return n1.add(n2).intValue();
}
}
面试题 66:构建乘积数组
public class F66{
public int[] multiply(int[] A) {
int length = A.length;
int[] B = new int[length];
if(length != 0 ){
B[0] = 1;
for(int i = 1; i < length; i++){
B[i] = B[i-1] * A[i-1];
}
int temp = 1;
for(int j = length-2; j >= 0; j--){
temp *= A[j+1];
B[j] *= temp;
}
}
return B;
}
G.两个面试案例
面试题 67:把字符串转换成整数
public class G67 {
private boolean valid=false;
public int strToInt(String str){
if (str==null || str.length()==0){
return 0;
}
boolean isNegative=false;
long number=0;
for (int i=0;i<str.length();i++){
if ( (i==0 && str.charAt(i)=='+') || (i==0&&str.charAt(0)=='-') ){
if (str.charAt(i)=='-'){
isNegative=true;
}
if (str.length()==1){
return 0;
}
continue;
}
if (str.charAt(i)<'0' || str.charAt(i)>'9'){
return 0;
}
int flag=isNegative?-1:1;
number=number*10+flag*(str.charAt(i)-'0');
if (!isNegative && number>Integer.MAX_VALUE || isNegative && number<Integer.MIN_VALUE){
return 0;
}
}
valid=true;
return (int) number;
}
}
面试题 68:树中的两个节点的最低公祖先
public class G68 {
private static class TreeNode{
private TreeNode left,right;
private int value;
}
public TreeNode find(TreeNode node1,TreeNode node2 ,TreeNode root){
int value=root.value;
if(value> node1.value&&value>node2.value){
return find(node1,node2,root.left);
}
if(value< node1.value&&value<node2.value){
return find(node1,node2,root.right);
}
return root;
}
private static class TreeNode1{
TreeNode1 parent;
private int value;
public TreeNode1(int value){
this.value=value;
}
}
public TreeNode1 find1(TreeNode1 node1,TreeNode1 node2){
if (node1==null || node2==null){
return null;
}
TreeNode1 cur1=node1;
TreeNode1 cur2=node2;
int len1=getLength(cur1);
int len2=getLength(cur2);
if (len1>len2){
node1=moveIndex(node1,len1,len2);
}
if (len2>len1){
node2=moveIndex(node2,len2,len1);
}
while (node1!=null&&node2!=null){
if(node1==node2){
return node1;
}
node1=node1.parent;
node2=node2.parent;
}
return null;
}
private int getLength(TreeNode1 node){
int length=0;
while (node!=null){
node=node.parent;
length++;
}
return length;
}
private TreeNode1 moveIndex(TreeNode1 node,int longLen,int shortLen){
for (int i = 0; i <longLen-shortLen ; i++) {
node=node.parent;
}
return node;
}
}