面试题目——《剑指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; 
    }
}
原文地址:https://www.cnblogs.com/tonglin0325/p/5527750.html