面试题目——《剑指Offer》
1.把一个字符串转换成整数(看面试题50)——《剑指Offer》P29
2.求链表中的倒数第k个结点(看面试题15)——《剑指Offer》P30
3.实现Singleton模式——《剑指Offer》P48
参考:http://www.cnblogs.com/tonglin0325/p/5196818.html
以及 http://wiki.jikexueyuan.com/project/for-offer/question-two.html
4.数组的内存是连续的,所以数组的时间效率很高,可以用来实现简单的哈希表——《剑指Offer》35题“第一个只出现一次的字母”
5.面试题3:二维数组中的查找——《剑指Offer》P55 Leecode 74题 相关题目:《leetcode》 21题 Merge Two Sorted Lists,提示:《剑指Offer》P66
提示;矩阵从右上角开始搜索,row和column
6.面试题4:替换空格——《剑指Offer》P61
7.面试题5:从尾到头打印链表——《剑指Offer》P68 《Leetcode》 206题 Reverse Linked List(leetcode写的算法速度太慢,待优化)
其他链表的题目:
8.面试题6:重建二叉树,由二叉树的前序遍历和中序遍历重建二叉树——《剑指Offer》P72 《Leetcode》 105和106题
思路:1.找到根节点 2.结束条件,返回 3.找到根节点在另一个遍历中的位置 4.计算左右子树长度 5.左右子树分别递归
其他二叉树的题目:
9.面试题7:用两个栈实现队列——《剑指Offer》P76 《Leetcode》232题 Implement Queue using Stacks 225题 Implement Stacks using Queue
其他栈和队列的题目:
10.面试题8:旋转数组的最小数字——《剑指Offer》P83 《leetcode》153题 Find Minimum in Rotated Sorted Array
思路:剑指Offer中是数组中没有重复数字的情况,利用二分查找结题,
相关题目:《左》第九章 getMin,以及在有序旋转数组中查找某个数
11.面试题9:斐波那契数列——《剑指Offer》P90 相关题目:青蛙跳台阶、变态跳台阶(注意Math.pow()返回的值是double,要转换成int)
相关题目:
12.面试题10:二进制中1的个数——《剑指Offet》P95 《leetcode》191题 Number of 1 Bits 两种解法,一种要移动32次,一种有多少1移动多少次
相关知识点:
13.面试题11:数值的整数次方——《剑指Offer》P107 注意:异常输入的处理 参考《leetcde》50题的解法和收藏博文的解法说明,记nlogn的解法
14.面试题12:打印1到最大的n位数——《剑指Offer》P111 两种解法
import java.util.Arrays; public class printN { public static void main(String[] args) throws Exception{ // TODO 自动生成的方法存根 //System.out.println(JumpFloor(4)); print1ToMaxOfN(2); } public static void print1ToMaxOfN(int n){ if(n<0) return; char[] number = new char[n]; Arrays.fill(number, '0'); while(!Increment(number)) PrintNumber(number); } public static boolean Increment(char[] number) { boolean isOverflow = false; int nTakeOver = 0; int nLen = number.length; for(int i=nLen-1;i>=0;i--){ //当没有进位的时候会break,循环只执行一遍,有进位会执行第二遍 int nSum = number[i]-'0'+nTakeOver; //加上进位 if(i==nLen-1) nSum++; if(nSum>=10){ if(i==0) isOverflow=true; else{ nSum -= 10; nTakeOver = 1; number[i]=(char)(nSum+48); //System.out.println(number); } }else{ number[i]=(char)(nSum+48); //System.out.println(number); break; } } //PrintNumber(number); return isOverflow; } public static void PrintNumber(char[] number){ boolean isBeginning0 = true; int nLen = number.length; for(int i=0;i<nLen;i++){ if(isBeginning0 && number[i] != '0') isBeginning0=false; if(!isBeginning0) System.out.print(number[i]); } System.out.println(); } }
15.面试题13:在O(1)时间删除链表结点——《剑指Offer》P116 分情况:1.结点为空 2.删除的是头结点 至少有两个结点 3.删除的是最后一个结点 4.删除的是中间的结点
参考:http://wiki.jikexueyuan.com/project/for-offer/question-thirteen.html《极客学院》
16.面试题14:调整数组顺序使奇数位于偶数前面——《剑指Offer》P119 《Leetcode》328题 Odd Even Linked List,这里是奇数和偶数结点
17.面试题15:链表中倒数第k个结点——《剑指Offer》P124 《Leetcode》19题 Remove Nth Node From End of List(leetcode测试用例有错,[1,2,3]移除倒数4的时候是[2,3]) 两种,一种遍历两遍,另一种遍历一遍
相关题目:
18.面试题16:反转链表——《剑指Offer》P129 《Leetcode》92和206题 Reverse Linked List
19.面试题17:合并两个排序的链表——《剑指Offer》P131 《Leetcode》21题 Merge Two Sorted Lists 剑指offer里面用的是递归,leetcode用的分情况
20.面试题18:树的子结构——《剑指Offer》P134 《牛客OJ》使用两个递归方法
21.面试题19:二叉树的镜像——《剑指Offer》P142 《牛客OJ》使用递归
22.面试题20:顺时针打印矩阵——《剑指Offer》P144 《Leetcode》54和59题 Spiral Matrix
23.面试题21:包含min函数的栈——《剑指Offer》P149 《Leetcode》 155题 Min Stack
24.面试题22:栈的压入、弹出序列——《剑指Offer》P154 《牛客OJ》栈的压入、弹出序列 注意.length<=0可以,而==null不行的问题
25.面试题23:从上往下打印二叉树——《剑指Offer》P157 注意返回的结果是ArrayList<Integer>还是ArrayList<ArrayList<Integer>>
26.面试题24:二叉搜索树的后序遍历序列——《剑指Offer》P157 《牛客OJ》注意Arrays.copyOfRange(sequence, 0, i)可以用来取数组的部分元素,前后的范围为[],root = sequence[len-1],所以取i而不是i-1
27.面试题25:二叉树中和为某一值的路径——《剑指Offer》P160 《Leetcode》112和113题 Path Sum 注意是输出是否,还是所有路径,DFS递归(难)
28.面试题26:复杂链表的复制——《剑指Offer》P164 《牛客OJ》里面讨论区中有3种方法
29.面试题27:二叉搜索树与双向链表——《剑指Offer》P168 《牛客OJ》递归的时候要把把pLastNodeInList设为全局变量,画图理解
30.面试题28:字符串的排列——《剑指Offer》P171 《牛客OJ》字符串的全排列,其中还要求字典排序,不单单只是列出所有的可能性(难)
相关题目:
31.面试题29:数组中出现次数超过一半的数字(在leetcode包中的MajorityElement)——《剑指Offer》P180 《Leetcode》169题 Majority Element
思路:声明一个count和temp,count代表temp出现的次数,当count等于0的时候temp = arr[i]
类似:Majority Element II ,数组中出现次数超过n/k的数字
思路:维护一个大小为k的map,当map的大小等于k-1的时候,map中的全部value减去1
32.面试题30:最小的k个数(GetLeastNumbers)——《剑指Offer》P184 两种:1.Partition算法 2.利用数组的特点,见Leetcode数组篇
思路:1.最简单的思路是把输入的n个数进行排序,然后取前k个数,算法的复杂度为O(nlogn)
2.利用堆排序的思想O(nlogk)
2.运用快排Partition的思想,就是先任意选取一个数,把小于这个值的数放在这个数左边,大于这个值的数放在右边,然后返回的值是这个值在数组中的位置,然后根据这个修改start或者end的值O(n)
33.面试题31:连续子数组的最大和——《剑指Offer》P188
思路:1.如果前n个相加小于0,那么最大的和只能从n+1个开始算
2.设curGreatestSum=Integer.VALUE_MIN,然后比较curSum和curGreatestSum
34.面试题32:从1到n整数中1出现的次数(NumberOf1Between1AndN)——《剑指Offer》P191
相关题目:只统计一个数的二进制表示中1的位数(Leetcode CountBits)
思路:1.一个数一个数的计算1的位数,然后相加,时间复杂度为O(nlogn)
2.寻找规律:534 = (个位1出现次数)+(十位1出现次数)+(百位1出现次数)=(53*1+1)+(5*10+10)+(0*100+100)= 214
注意:int n = Integer.parseInt("123"); //将字符串转化成整形
String s = String.valueOf(int a ); //将整形转化为字符串
int[] is = {1,2,3,4};
String str = Arrays.toString(is); //字符数组转化成字符串
35.面试题33:把数组排成最小的数——《剑指Offer》P194 《Leetcode》179题 Largest Number
思路:使用sort排序,重点是重新建立排序规则,重写用于排序的Comparator
36.面试题34:求从小到大的第N个丑数(我们把只包含因子2、3和5的数成为丑数,习惯上把1当作第一个丑数)
思路:第1种解法.是遍历所有的数,%2,%3,%5是都==0
第2种解法
1.首先第一个丑数是1
2.第2个丑数是1乘以2,3,5中结果大于1的最小的一个
3.第3个丑数是1乘以3,5,和2乘以2的结果中最小的一个
37.面试题35:第一个只出现一次的字符——《剑指Offer》P203
思路:使用HashMap,注意输入的时候使用Scan循环检测
38.面试题36:数组中的逆序对——《剑指Offer》P206
思路:利用递归的方法,通过增加空间O(N),把空间复杂度O(N^2)降到O(NlogN)
39.面试题37:两个链表中的第一个公共节点——《剑指Offer》P210 《Leetcode》160题 Intersection of Two Linked Lists
思路:先把长的链表的表头向后移动,直到两个链表的长度相等,然后同时移动找到公共节点
40.面试题38:数字在排序数组中出现的次数——《剑指Offer》P221
思路:使用递归和二分查找的思想,分别求得第一个数字出现的位置和最后一个数字出现的位置
41.面试题39:二叉树的深度——《剑指Offer》P224
思路:1.使用递归的思想——参考《Leetcode》110题 Balanced Binary Tree,查找左右子树的最大深度
2.在《Leetcode》的110题中还有一种每个结点只遍历一次的解法//不会
42.面试题40:数组中只出现一次的数字(有两个)——《剑指Offer》P228
思路:1.在一个数组中出现一次的数字有2个,所以首先要把这个数组分成两个数组,把数组中的每个数用二进制表示并做异或运算,因为相同的数异或之后为0,所以最后的结果是两个只出现1次的数异或之后的结果
2.然后根据这个异或的结果,比如0010,根据最右边一位,也就是倒数第2位是否为1,把数组分成两个
3.对两个数组分别做异或,异或的结果就是要求的数的值
43.面试题41:和为s的两个数字——《剑指Offer》P231
思路:因为数组是已经排好序的,所以设start和end,如果sum小于所要求的和就start++,大于end--
44.面试题42:和为s的连续正数序列,比如10的是1,2,3,4——《剑指Offer》P231
思路:和上一题目的方法类似,设small为1,big为2,然后序列和大于要求的目标small++,小于就big++,注意small<(sum+1)/2)的情况不用计算
45.面试题43:翻转单词顺序,比如"I am a student."->"student. a am I"——《剑指Offer》P235
思路:1.首先翻转所有字符的顺序,"I am a student."->".tneduts a ma I"
2.然后在翻转每个单词中字符的顺序,".tneduts a ma I"->"student. a am I"
46.面试题44:左旋转字符串,比如输入字符串"abcdefg"和数字2,函数返回左旋转2位得到的结果"cdefgab"——《剑指Offer》P235
思路:1.首先按照给定的数组2,把字符串分成"ab"和"cdefg"两个部分,分别旋转这两个部分,"abcdefg"->"bagfedc"
2.在翻转整个字符串,得到"bagfedc"->"cdefgab"
或者直接用n%length,之后用java的subString方法
47.面试题45:n个骰子的点数,n个骰子,所有骰子朝上一面的点数之和为s,打印出s的所有可能的值出现的概率——《剑指Offer》P240
思路:比较难
48.面试题46:扑克牌的顺子,从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的,A为1,J为11,Q为12,K为13,大小王为任意数字——《剑指Offer》P243
思路:1.首先对数组进行排序
2.然后统计数组中numberOfZero和numberOfGap,如果numberOfZero>=numberOfGap就返回True
注意数组中有对子的话,不是顺子
49.面试题47:圆圈中最后剩下的数字,n个数字围成一个圈,每次删除第m个数字,求最后剩下的数字(约瑟夫环问题)——《剑指Offer》P245
思路:1.采用环形链表来模拟圆圈
2.利用公式(代码量很少,且时间空间复杂度优于第一种方法,用递归或者循环实现)
50.面试题48:求1+2+……+n,不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)——《剑指Offer》P250
思路:1.使用递归的思想
51.面试题49:不用加减乘除做加法,求两个整数只和,不能使用加减乘除——《剑指Offer》P254
思路:1.求两个数的异或,异或结果为不包含进位的和
2.求两个数与运算后的结果,并向左移1位,这个为进位的结果
3.把异或结果和进位结果相加,但是不能使用加法,就是把这个方法循环
52.面试题50:把字符串变成整数(atoi函数)——《剑指Offer》P261 《Leetcode》第8题 String to Integer (atoi)
思路:1.去掉首尾的空格
2.检查符号位
3.用double型来存储(double result),因为可能超过Long.MAX_VALUE,9223372036854775807
4.循环字符串的每一位,从非符号位的第一位开始,到第一个非数字位结束
5.如果flag是'-',result取反
6.检查有没有越界——大于Integer.MAX_VALUE则返回Integer.MAX_VALUE,小于Integer.MIN_VALUE,则返回Integer.MIN_VALUE,否则返回(int) result
53.面试题51:树中两个结点的最低公共祖先——《剑指Offer》P269 《Leetcode》235题 Lowest Common Ancestor of a Binary Search Tree
236题Lowest Common Ancestor of a Binary Tree
思路:1.如果树是二叉搜索树,即一个结点的左子树都比这个结点小,右子树都比这个结点大。
输入两个结点,那么从根节点开始,如果这两个结点都比根节点小,那么这两个结点都在左子树中,一直直到两个结点一个比某个结点小,一个比某个结点大,那么这个结点都是最低的公共祖先。
2.如果树不是二叉搜索树,但是每个子结点都有指向它的父结点,这个问题就变成了求两个链表的第一个交点。
3.如果树既不是二叉搜索树,子结点也没有指向父结点。用两个链表记录根节点到两个结点的路径,然后把问题转换成求两个链表的最后一个公共结点
或者利用递归的思想,进行后序遍历
public class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if (root == null || p == null || q == null) { return null; } // If any of the node is the root, just return the root. if (root == p || root == q) { return root; } // if no node is in the node, just recursively find it in LEFT and RIGHT tree. TreeNode left = lowestCommonAncestor(root.left, p, q); TreeNode right = lowestCommonAncestor(root.right, p, q); if (left == null) { // If didn't found in the left tree, then just return it from right. return right; } else if (right == null) { // Or if didn't found in the right tree, then just return it from the left side. return left; } // if both right and right found a node, just return the root as the Common Ancestor. return root; } }
本文只发表于博客园和tonglin0325的博客,作者:tonglin0325,转载请注明原文链接:https://www.cnblogs.com/tonglin0325/p/5527750.html