02 单例模式

单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。

从具体实现角度来说,主要有三点:一是单例模式的类只提供私有的构造函数,二是类定义中含有一个该类的静态私有对象,三是该类提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象。

// 懒汉式-线程不安全
public class Singleton { private static Singleton uniqueInstance; private Singleton() {
} public static Singleton getUniqueInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
} // 双重校验锁-线程安全
public class Singleton { private volatile static Singleton uniqueInstance; private Singleton() {
} public static Singleton getUniqueInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
} // 静态内部类实现
public class Singleton { private Singleton() {
} private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
} public static Singleton getUniqueInstance() {
return SingletonHolder.INSTANCE;
}
}

03 数组中重复的数字

/**
* 03 数组中重复的数字
* 在一个长度为 n 的数组里的所有数字都在 0 到 n-1 的范围内。数组中某些数字是重复的,但不知道 有几个数字是重复的,也不知道每个数字重复几次。请找出数组中任意一个重复的数字。
*/ public class _03 {
public static boolean duplicate(int[] numbers,int length,int[] duplication) {
int [] array = new int[length];
for (int i = 0; i < length; ++i) {
if (array[numbers[i]] == 0) {
array[numbers[i]] = 1;
} else {
duplication[0] =numbers[i];
return true;
}
}
return false;
} public static void main(String[] args) {
int[] numbers = {2, 3, 1, 0, 2, 5, 3};
int[] duplication = new int[1];
System.out.println(duplicate(numbers, numbers.length, duplication) + " " + duplication[0]);
}
}

04 二维数组中的查找

/**
* 04 二维数组中的查找
* 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。 请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
*/
public class _04 {
public static boolean find(int target, int [][] array) {
if (array == null || array.length == 0) {
return false;
}
if (array[0].length == 0) {
return false;
}
int col = array[0].length;
int row = array.length;
int i = row - 1;
int j = 0;
while (j < col && i >= 0) {
if (array[i][j] == target) {
return true;
} else if (array[i][j] > target) {
i--;
} else {
j++;
}
}
return false;
} public static void main(String[] args) {
int[][] array = {{1, 4, 7, 11, 15},
{2, 5, 8, 12, 19}};
System.out.println("Find(5, array) = " + find(5, array));
}
}

05 替换空格

/**
* 05 替换空格
* 请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过 替换之后的字符串为We%20Are%20Happy。
*
* 在字符串尾部填充任意字符,使得字符串的长度等于替换之后的长度。因为一个空格要替换成三个字符 (%20),因此当遍历到一个空格时,需要在尾部填充两个任意字符。
* 令 P1 指向字符串原来的末尾位置,P2 指向字符串现在的末尾位置。P1 和 P2 从后向前遍历,当 P1 遍历到一个空格时,就需要令 P2 指向的位置依次填充 02%(注意是逆序的),否则就填充上 P1 指向字符的值。
* 从后向前遍是为了在改变 P2 所指向的内容时,不会影响到 P1 遍历原来字符串的内容
*/ public class _05 {
public static String replaceSpace(StringBuffer str) {
int originalLength = str.length();
for (int i = 0; i < originalLength; ++i) {
if (str.charAt(i) == ' ') {
// 每遇到一个空格扩充2个长度
str.append(" ");
}
}
int newLength = str.length();
int j = newLength - 1;
for (int i = originalLength - 1; i >= 0; --i) {
if (str.charAt(i) == ' ') {
str.setCharAt(j--, '0');
str.setCharAt(j--, '2');
str.setCharAt(j--, '%');
} else {
str.setCharAt(j--, str.charAt(i));
}
}
return str.toString();
} public static void main(String[] args) {
replaceSpace(new StringBuffer("We Are Happy"));
}
}

06 从头到尾打印链表

import java.util.ArrayList;
import java.util.List;
import java.util.Stack; /**
* 06 从头到尾打印链表
* 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
*/ /**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*
*/
public class _06 {
/**
* 使用堆栈
* @param listNode 链表头结点
* @return 反向打印所有值
*/
public static ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
if (listNode == null) {
return new ArrayList<>();
}
Stack<Integer> stack = new Stack<>();
ArrayList<Integer> arrayList = new ArrayList<>();
while (listNode != null) {
stack.push(listNode.val);
listNode = listNode.next;
}
while (!stack.empty()) {
arrayList.add(stack.pop());
}
return arrayList;
} /**
* 使用递归
* @param listNode 链表头结点
* @return 反向打印所有值
*/
public static ArrayList<Integer> printListFromTailToHead1(ListNode listNode) {
if (listNode == null) {
return new ArrayList<>();
}
ArrayList<Integer> arrayList = printListFromTailToHead1(listNode.next);
arrayList.add(listNode.val); return arrayList;
} /**
* 使用头插法
* 构建一个头指针head,初始head->next = null,然后不断将listNode中的节点加到head后 面,相当于反向链表
* @param listNode 链表头结点
* @return 反向打印所有值
*/
public static ArrayList<Integer> printListFromTailToHead2(ListNode listNode) {
if (listNode == null) {
return new ArrayList<>();
}
// 头指针
ListNode head = new ListNode(0);
head.next = null; // 将listNode中的结点逐步加到head后面
while (listNode != null) {
// 先存储下一个结点
ListNode nextNode = listNode.next;
// 头插
listNode.next = head.next;
head.next = listNode;
// 继续下一次循环
listNode = nextNode;
} ArrayList<Integer> arrayList = new ArrayList<>();
// 头结点
listNode = head.next;
while (listNode != null) {
arrayList.add(listNode.val);
listNode = listNode.next;
}
return arrayList;
} public static void main(String[] args) {
// 构造一个链表
ListNode listNode1 = new ListNode(1);
ListNode listNode2 = new ListNode(2);
listNode2.next = null;
listNode1.next = listNode2; List<Integer> list = printListFromTailToHead2(listNode1);
for (Integer integer : list) {
System.out.println(integer + " ");
}
} /**
* 内部类:相当于一个链表节点
*/
public static class ListNode {
int val;
ListNode next = null; ListNode(int val) {
this.val = val;
}
} }

07 重建二叉树

/**
* 07 重建二叉树
* 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结 果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列 {4,7,2,1,5,3,8,6},则重建二叉树并返回。
* 前序遍历的第一个值为根节点的值,使用这个值将中序遍历结果分成两部分,左部分为树的左子树中序 遍历结果,右部分为树的右子树中序遍历的结果,然后就可以接着分别对左右子树递归下去。
*/ /**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class _07 { /**
* 重建二叉树
* @param pre 前序遍历
* @param in 中序遍历
* @return 返回重建的二叉树
*/
public static TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if (pre == null || in == null || pre.length == 0 || in.length == 0) {
return null;
}
return reConstructBinaryTree(pre, in, 0, pre.length - 1, 0, in.length - 1);
} /**
* 扩充前序与中序的索引参数,便于递归重建二叉树
* @param pre 前序遍历
* @param in 中序遍历
* @param preStart 前序遍历数组的开始索引
* @param preEnd 前序遍历数组的结束索引
* @param inStart 中序遍历数组的开始索引
* @param inEnd 中序遍历数组的结束索引
* @return 返回重建的二叉树
*/
private static TreeNode reConstructBinaryTree(int [] pre,int [] in, int preStart, int preEnd, int inStart, int inEnd) {
if (preStart > preEnd) {
return null;
}
// 根节点的值是前序遍历的第一个值
int rootValue = pre[preStart];
TreeNode treeNode = new TreeNode(rootValue);
// 找到中序遍历序列中的根节点的位置,递归得到左右节点
for (int i = inStart; i <= inEnd; ++i) {
if (in[i] == pre[preStart]) {
treeNode.left = reConstructBinaryTree(pre, in, preStart + 1, preStart + i - inStart, inStart, i - 1);
treeNode.right = reConstructBinaryTree(pre, in, preStart + i - inStart + 1, preEnd, i + 1, inEnd);
break;
}
}
return treeNode;
} public static void main(String[] args) {
int[] pre = {1, 2, 4, 7, 3, 5, 6, 8};
int[] in = {4, 7, 2, 1, 5, 3, 8, 6};
reConstructBinaryTree(pre, in);
} /**
* 内部类:二叉树结构
*/
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
}

08 二叉树的下一个结点

/**
* 08 二叉树的下一个结点
* 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不 仅包含左右子结点,同时包含指向父结点的指针
* 分三种情况:
* (1)当前节点有右子树,则下一个中序遍历节点是右子树中的最左节点
* (2)当前节点没有右子树,且该节点是其父节点的左节点,则下一个节点是其父节点
* (3)当前节点没有右子树,且该节点是其父节点的右节点,则沿着其父节点向上遍历,直到找到一个 是其父节点的左节点的节点,这个节点的父节点即为所求
*/
/**
public class TreeLinkNode {
int val;
TreeLinkNode left = null;
TreeLinkNode right = null;
TreeLinkNode next = null; TreeLinkNode(int val) {
this.val = val;
}
}
*/
public class _08 { public static TreeLinkNode GetNext(TreeLinkNode pNode) {
if (pNode == null) {
return null;
}
// 当前节点有右子树
if (pNode.right != null) {
pNode = pNode.right;
while (pNode.left != null) {
pNode = pNode.left;
}
return pNode;
}
// 当前节点没有右子树,且该节点没有父节点,是根节点
if (pNode.next == null) {
return null;
}
// 当前节点没有右子树,且该节点是其父节点的左节点
if (pNode.next.left == pNode) {
return pNode.next;
}
// 当前节点没有右子树,且该节点是其父节点的右节点
if (pNode.next.right == pNode) {
pNode = pNode.next;
while (pNode.next != null) {
if (pNode.next.left != pNode) {
pNode = pNode.next;
} else {
return pNode.next;
}
}
}
return null;
} /**
* 二叉树结构,包含了指向其父节点的指针
*/
public static class TreeLinkNode {
int val;
TreeLinkNode left = null;
TreeLinkNode right = null;
TreeLinkNode next = null; TreeLinkNode(int val) {
this.val = val;
}
}
}

09 用两个栈实现队列

import java.util.Stack;

/**
* 09 用两个栈实现队列
* 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型
* 栈1的push对应队列的deleteHead操作,栈2的pop操作对应队列的insertTail操作,当栈2为空时, 将栈1的元素依次出栈,进到栈2中,如果栈1也为空,则提示队列为空
*/ public class _09 {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>(); /**
* 队列的insertTail操作
* @param node 插入队尾的元素
*/
public void push(int node) {
stack1.push(node);
} /**
* 队列的deleteHead操作
* @return 删除队列头部
*/
public int pop() {
if (stack2.empty()) {
if (stack1.empty()) {
throw new RuntimeException("队列为空");
} else {
while (!stack1.isEmpty()) {
stack2.push(stack1.pop());
}
}
}
return stack2.pop();
}
}

10 斐波那契数列

/**
* 10 斐波那契数列
* 大家都知道斐波那契数列,后一项等于前两项和,现在要求输入一个整数n,请你输出斐波那契数列的 第n项(从0开始,第0项为0,n<=39)。
* 使用两个数将结果前两项缓存即可
*/ public class _10 {
public static int Fibonacci(int n) {
int result = 0;
int temp1 = 0;
int temp2 = 1;
if (n == 1) {
return temp2;
}
for (int i = 1; i < n; i++) {
result = temp1 + temp2;
temp1 = temp2;
temp2 = result;
}
return result;
} public static void main(String[] args) {
System.out.println("Fibonacci(3) = " + Fibonacci(3));
}
}

剑指offer题解02-10的更多相关文章

  1. 剑指offer题解(Java版)

    剑指offer题解(Java版) 从尾到头打印链表 题目描述 输入一个链表,按从尾到头的顺序返回一个ArrayList. 方法1:用一个栈保存从头到尾访问链表的每个结点的值,然后按出栈顺序将各个值存入 ...

  2. 剑指offer(leetcode 10.) 正则表达式匹配

    这题一年前就做过,当时刚开始刷leetcode,提交了几十次过不去,就放那没管了.今天剑指offer又遇到这题,终于做出来了,用的dp. class Solution { public: bool i ...

  3. 剑指offer题解

    数组中重复的数字 题目描述:在一个长度为n的数组里面的所有数字都在0~n-1的范围内.数组中某些数字是重复的,但是不知道有几个数字重复了,也不知道每个数字重复了几次,请找出数组中任意一个重复的数字.例 ...

  4. 剑指Offer题解(Python版)

    https://blog.csdn.net/tinkle181129/article/details/79326023# 二叉树的镜像    链表中环的入口结点    删除链表中重复的结点    从尾 ...

  5. 剑指offer第二版-10.斐波那契数列

    面试题10:斐波那契数列 题目要求: 求斐波那契数列的第n项的值.f(0)=0, f(1)=1, f(n)=f(n-1)+f(n-2) n>1 思路:使用循环从下往上计算数列. 考点:考察对递归 ...

  6. 剑指offer——面试题10:斐波那契数列

    个人答案: #include"iostream" #include"stdio.h" #include"string.h" using na ...

  7. 【剑指Offer】02、替换空格

    题目描述 请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 题解:StringBuffer ...

  8. 剑指Offer题解索引

    数组 数组中重复的数字 二维数组中的查找 构建乘积数组 字符串 替换空格 字符流中第一个不重复的字符 表示数值的字符串 递归和循环 斐波那契数列 跳台阶 变态跳台阶 矩形覆盖 链表 从尾到头打印链表 ...

  9. 剑指offer【02】- 替换空格(Java)

    题目:替换空格 考点:字符串 题目描述: 请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. ...

随机推荐

  1. Django(模板语言-自定义filter和simple_tag)

    Django(模板语言-自定义filter和simple_tag)   filter过滤器的主要形式:变量|函数,意思是将变量交给函数处理,而自定义filter就是自己定义函数,因为用到已有的很少. ...

  2. Django model :add a non-nullable field 'SKU' to product without a default; we can't do that

    You are trying to add a non-nullable field 'SKU' to product without a default; we can't do that (the ...

  3. js 跳转的几种方法收藏

    history.go(-n) 返回上一页(n 为返回前几页) window.location.reload(); 刷新当前页面 history.go(-1);window.locatoin.reloa ...

  4. 关于mariadb远程连接授权的设置

    1.首先配置允许访问的用户,采用授权的方式给用户权限 1 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'IDENTIFIED BY '123456' WITH GR ...

  5. 【BZOJ4543】[POI2014]Hotel加强版 长链剖分+DP

    [BZOJ4543][POI2014]Hotel加强版 Description 同OJ3522数据范围:n<=100000 Sample Input 7 1 2 5 7 2 5 2 3 5 6 ...

  6. css3动画效果:1基础

    css动画分两种:过渡效果transition .关键帧动画keyframes 一.过渡效果transition 需触发一个事件(如hover.click)时,才改变其css属性. 过渡效果通常在用户 ...

  7. IIS7发布wcf服务遇到的问题

    如果没有上图所列出的asp.net 40,请在cmd中运行:C:\Windows\Microsoft.NET\Framework\V4.0.30319\aspnet_regiis -i 注:C:\Wi ...

  8. http://element.eleme.io/#/zh-CN/component/quickstart

    http://element.eleme.io/#/zh-CN/component/quickstart

  9. Python位运算符

    按位运算符是把数字看作二进制来进行计算的.Python中的按位运算法则如下: 下表中变量 a 为 60,b 为 13,二进制格式如下: a = 0011 1100 b = 0000 1101 ---- ...

  10. 安装MySQL版本为mysql-installer-community-5.7.17.msi

    双击MySQL安装包, 勾选复选框,点击下一步: 选择仅仅服务器模式,点击下一步: 直接点击执行: 执行完成,点击下一步: 确认配置,点击下一步: 输入用户名和密码,点击下一步: 默认选项,点击下一步 ...