设计一个类,我们只能生成该类的一个实例。
饿汉式
懒汉式
线程不安全
线程安全
在方法上添加synchronized
双重校验锁*
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
...
静态内部类*
private static class SingletonHolder {
private static final Singleton INSTANCE =
new Singleton();
}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
...
枚举*
public enum Singleton {
INSTANCE;
public void whateverMethod() {
...
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
左下/右上
请实现一个函数,把字符串中的每个空格替换成"%20"。例如输入“We are happy.”,则输出“We%20are%20happy.”。
输入一个链表的头结点,从尾到头反过来打印出每个结点的值。
栈
递归
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
用两个栈实现一个队列。分别完成在队列尾部插入结点和在队列头部删除结点的功能。
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。
二分法
递归
循环
一只青蛙一次可以跳上1 级台阶,也可以跳上2 级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
用 2×1的小矩形横着或者竖着去覆盖更大的矩形。请问用8个2×1的小矩形无重叠地覆盖一个2×8的大矩形,总共有多少种方法?
请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。
正数
考虑负数
实现函数 double Power(double base, int exponent),求 base的exponent次方。
输入数字n,按顺序打印出从1最大的n位十进制数。比如输入3,则打印出1、2、3一直到最大的3位数即999。
给定单向链表的头指针和一个结点指针,定义一个函数在 O(1)时间删除该结点。
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
输入一个链表,输出该链表中倒数第 k 个结点。
设置两个指针 第一个指针先走k-1步 然后两个指针一起走 直到第一个指针走到末尾
注意程序鲁棒性
举一反三
定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。
输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。
输入两棵二叉树A和B,判断B是不是A的子结构。
完成一个函数,输入一个二叉树,该函数输出它的镜像。
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。
从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印。
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。
输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。
在复杂链表中,每个结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling 指向链表中的任意结点或者NULL。
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
输入一个字符串,打印出该字符串中字符的所有排列。
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
输入n个整数,找出其中最小的k个数。
使用快速排序 直到标准值等于k 则前半段为结果
建立k大小的最大堆 依次填充至满 继续比较堆最大值与数组中其他数字的大小 若小于则替换
最大堆
输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。
输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。
分析
解法
取第 i 位左边的数字(高位),乘以 10 ^(i−1) ,得到基础值 a 。
取第 i 位数字,计算修正值:
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
Arrays.sort(strs, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
String s1 = o1 + o2;
String s2 = o2 + o1;
return s1.compareTo(s2);
...
我们把只包含因子2、3和5的数称作丑数(Ugly Number)。求按从小到大的顺序的第1500个丑数。
在字符串中找出第一个只出现一次的字符。如输入"abaccdeff",则输出’b’。
在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
归并排序
在比较时加入全局变量count
data[start]>=data[index]
count = mid+1-start
输入两个链表,找出它们的第一个公共结点。
将两个链表放入两个栈中
弹出直到不相等
上一个弹出的值就是第一个公共结点
得到两个结点的长度
两个指针指向链表头部
长的链表指针先走长度差
然后一起走 第一个相同的结点就是公共结点
统计一个数字在排序数组中出现的次数。例如输入排序数组{1,2, 3,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4。
输入一棵二叉树的根结点,求该树的深度。
二叉树深度为左右子树中深度较大值+1
private static int getDepth(Tree root) {
if (root == null)
return 0;
int left = getDepth(root.left);
int right = getDepth(root.right);
return left > right ? left + 1 : right + 1;
...
输入一棵二叉树的根结点,判断该树是不是平衡二叉树。
if (root == null) return true;
boolean condition = Math.abs(getDepth(root.left) - getDepth(root.right)) <= 1;
return condition && isBalanced(root.left) && isBalanced(root.right);
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是 O(n),空间复杂度是O(1)。
a 异或/^ a = 0
a 异或/^ 0 = a
xxx1 & 1 = 1
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,输出任意一对即可。
输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以结果打印出3个连续序列1~5、4~6和7~8。
输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student.",则输出"student.a am I"。
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如输入字符串"abcdefg"和数字2,该函数将返回左旋转2位得到的结果"cdefgab"。
把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。
从扑克牌中随机抽 5张牌,判断是不是一个顺子,即这 5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王可以看成任意数字。
0,1,…,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
公式
循环链表模拟
求1+2+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
private static int sum(int n) {
int sum = n;
boolean result = (n > 0) && ((sum += sum(n - 1)) > 0);
return sum;
...
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、×、÷四则运算符号。
private static int add(int a, int b) {
while (b != 0) {
int temp = a ^ b;
b = (a & b) << 1;
a = temp;
}
return a;
...
二叉搜索树